summary refs log blame commit diff stats
path: root/README
blob: 07837688d791751e55d3e0f8a650c3d51d569b0f (plain) (tree)
1
2
3
4
5
6
7
8
9
# some utilities for converting numbers from hex
# lowercase letters only for now

== code
#   instruction                     effective address                                                   register    displacement    immediate
# . op          subop               mod             rm32          base        index         scale       r32
# . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes

hex-int?:  # in: (addr slice) -> result/eax: boolean
    # . prologue
    55/push-ebp
    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
    # . save registers
    51/push-ecx
    52/push-edx
    53/push-ebx
    # ecx = s
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
    # edx = s->end
    8b/copy                         1/mod/*+disp8   1/rm32/ecx    .           .             .           2/r32/edx   4/disp8         .                 # copy *(ecx+4) to edx
    # var curr/ecx: (addr byte) = s->start
    8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # copy *ecx to ecx
    # if s is empty return false
    b8/copy-to-eax  0/imm32/false
    39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
    73/jump-if-addr>=  $hex-int?:end/disp8
    # skip past leading '-'
    # . if (*curr == '-') ++curr
    31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
    8a/copy-byte                    0/mod/indirect  1/rm32/ecx    .           .             .           3/r32/BL    .               .                 # copy byte at *ecx to BL
    81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x2d/imm32/-      # compare ebx
    75/jump-if-!=  $hex-int?:initial-0/disp8
    # . ++curr
    41/increment-ecx
    # skip past leading '0x'
$hex-int?:initial-0:
    # . if (*curr != '0') jump to loop
    31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
    8a/copy-byte                    0/mod/indirect  1/rm32/ecx    .           .             .           3/r32/BL    .               .                 # copy byte at *ecx to BL
    81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x30/imm32/0      # compare ebx
    75/jump-if-!=  $hex-int?:loop/disp8
    # . ++curr
    41/increment-ecx
$hex-int?:initial-0x:
    # . if (curr >= in->end) return true
    39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
    73/jump-if-addr>=  $hex-int?:true/disp8
    # . if (*curr != 'x') jump to loop  # the previous '0' is still valid so doesn't need to be checked again
    31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
    8a/copy-byte                    0/mod/indirect  1/rm32/ecx    .           .             .           3/r32/BL    .               .                 # copy byte at *ecx to BL
    81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x78/imm32/x      # compare ebx
    75/jump-if-!=  $hex-int?:loop/disp8
    # . ++curr
    41/increment-ecx
$hex-int?:loop:
    # if (curr >= in->end) return true
    39/compare   
Ranger v.1.0.4
==============

Ranger

   A keeper, guardian, or soldier who ranges over a region
   to protect the area or enforce the law.

This is the filemanager Chuck Norris the Texas Ranger would use
if he had a computer with a unix-like operating system.  (He doesn't
trust computers though and prefers to do the calculations himself.)

After all, as a professional ranger, he needs a broad overview of his
territory, and the multi-column display of ranger provides just that,
rather than restricting you to the current directory only.
You can preview the content of the selected file or directory, copy or move
files around with the VIM-like commands dd and yy, execute predefined
applications when opening a file, etc...

Everything is fully customizable and written in Python (2.6 and 3.1
compatible) using curses for the text-based user interface.


About
-----

* Author:          Roman Zimbelmann
* Email:           romanz@lavabit.com
* Website:         http://savannah.nongnu.org/projects/ranger
* Git repo:        http://git.savannah.gnu.org/cgit/ranger.git
* Version:         1.0.4


Features
--------

* Multi-column display
* Preview of the selected file/directory
* Common file operations (create/chmod/copy/delete/...)
* Quickly find files or text inside files
* VIM-like console and hotkeys
* Open files in external programs
* Mouse support
* Change the directory of your shell after exiting ranger
* Bookmarks


Dependencies
------------

* A Unix-like Operating System
* Python 2.6 or 3.1
* Python curses module  (often but not always included with Python)


Bugs and Feature Requests
-------------------------

Report bugs and feature requests on savannah:
    https://savannah.nongnu.org/bugs/?func=additem&group=ranger

Alternatively you can send an email to romanz@lavabit.com.

Please include as much relevant information as possible.
Using ranger with the --debug option will abort the program and
print tracebacks rather than a red message in the statusbar.
If this applies to you, please include such a traceback in your report.


Getting Started
---------------

If you just want to check out ranger without installing it, type

    ./ranger.py --clean

in the top directory of ranger.  By using the --clean switch, it will
leave no trace on your system whatsoever.

To properly install it, follow the instructions in the INSTALL file,
then type:

    ranger

You should see 4 columns.  The third is the directory where you are at
the moment.  To the left, there are the directories above the current
working directory, and the column on the right is a preview of the selected
file/directory.

Now use the arrow keys to navigate, press enter to open a file.

A list of commands with short descriptions can be viewed by
pressing "?" inside the program and following the instructions.
The file ranger/defaults/keys.py contains all key combinations, so that's
another place you may want to check out.


Opening Files with Ranger
-------------------------

If you use the same applications like me, you'll be able to open
files by pressing the right arrow key.  If not, you will have to
specify them in ranger/defaults/apps.py.  It's explained
in the docstrings how exactly to do that.

Once you've set up your applications, you can also use ranger to
open files from the shell:
    ranger blabla.pdf


Customizing Ranger
------------------

The file ranger/defaults/options.py contains most of the options.
apps.py defines how files are run, keys.py defines keybindings.

The files in ranger/defaults/ can be copied into ~/.ranger/ for per-user
modifications.  Colorschemes can be placed in ~/.ranger/colorschemes.

The configuration files should be self-explanatory.  If you need more
information, check out the source code.

Also, see the file HACKING for more detailed instructions on
modifying the program.


Tips
----

Change the directory of your parent shell when you exit ranger:

ranger() {
    $(which ranger) $@ &&
    cd "$(grep \^\' ~/.ranger/bookmarks | cut -b3-)"
}

This can be put into your ~/.bashrc or something similar.
. 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-hex-int-handles-0x-prefix: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "0x3a" b8/copy-to-eax "0x3a"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = hex-int?(slice) # . . push args 51/push-ecx # . . call e8/call hex-int?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-hex-int-handles-0x-prefix"/imm32 68/push 1/imm32/true 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-hex-int-handles-negative: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "-34a" b8/copy-to-eax "-34a"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = hex-int?(slice) # . . push args 51/push-ecx # . . call e8/call hex-int?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-hex-int-handles-negative"/imm32 68/push 1/imm32/true 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-hex-int-handles-negative-0x-prefix: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "-0x3a" b8/copy-to-eax "-0x3a"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = hex-int?(slice) # . . push args 51/push-ecx # . . call e8/call hex-int?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-hex-int-handles-negative-0x-prefix"/imm32 68/push 1/imm32/true 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return parse-hex-int: # in: (addr array byte) -> result/eax: int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx 52/push-edx # eax = in 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax # var curr/ecx: (addr byte) = &in->data 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy eax+4 to ecx # var max/edx: (addr byte) = &in->data[in->size] # . edx = in->size 8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx # . edx = in->data + in->size 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx # return parse-hex-int-helper(curr, max) # . . push args 52/push-edx 51/push-ecx # . . call e8/call parse-hex-int-helper/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp $parse-hex-int:end: # . restore registers 5a/pop-to-edx 59/pop-to-ecx # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return parse-hex-int-from-slice: # in: (addr slice) -> result/eax: int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx 52/push-edx # ecx = in 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # var max/edx: (addr byte) = in->end 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx # var curr/ecx: (addr byte) = in->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 1/r32/ecx . . # copy *ecx to ecx # return parse-hex-int-helper(curr, max) # . . push args 52/push-edx 51/push-ecx # . . call e8/call parse-hex-int-helper/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp $parse-hex-int-from-slice:end: # . restore registers 5a/pop-to-edx 59/pop-to-ecx # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return parse-hex-int-helper: # start: (addr byte), end: (addr byte) -> result/eax: int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx 52/push-edx 53/push-ebx 56/push-esi # var curr/ecx: (addr byte) = start 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # edx = max 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx # var result/ebx: int = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx # var negate?/esi: boolean = false 31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi $parse-hex-int-helper:negative: # if (*curr == '-') ++curr, negate = true 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 3d/compare-eax-and 0x2d/imm32/- 75/jump-if-!= $parse-hex-int-helper:initial-0/disp8 # . ++curr 41/increment-ecx # . negate = true be/copy-to-esi 1/imm32/true $parse-hex-int-helper:initial-0: # skip past leading '0x' # . if (*curr != '0') jump to loop 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 3d/compare-eax-and 0x30/imm32/0 75/jump-if-!= $parse-hex-int-helper:loop/disp8 # . ++curr 41/increment-ecx $parse-hex-int-helper:initial-0x: # . if (curr >= in->end) return result 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $parse-hex-int-helper:end/disp8 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 3d/compare-eax-and 0x78/imm32/x 75/jump-if-!= $parse-hex-int-helper:loop/disp8 # . ++curr 41/increment-ecx $parse-hex-int-helper:loop: # if (curr >= in->end) break 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $parse-hex-int-helper:negate/disp8 # var eax: int = from-hex-char(*curr) # . . copy arg to eax 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL # . . call e8/call from-hex-char/disp32 # result = result * 16 + eax c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 4/imm8 # shift ebx left by 4 bits 01/add 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # add eax to ebx # ++curr 41/increment-ecx # loop eb/jump $parse-hex-int-helper:loop/disp8 $parse-hex-int-helper:negate: # if (negate?) result = -result 81 7/subop/compare 3/mod/direct 6/rm32/esi . . . . . 0/imm32/false # compare esi 74/jump-if-= $parse-hex-int-helper:end/disp8 f7 3/subop/negate 3/mod/direct 3/rm32/ebx . . . . . . # negate ebx $parse-hex-int-helper:end: # return result 89/copy 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # copy ebx to eax # . restore registers 5e/pop-to-esi 5b/pop-to-ebx 5a/pop-to-edx 59/pop-to-ecx # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-parse-hex-int-from-slice-single-digit: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "a" b8/copy-to-eax "a"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = parse-hex-int-from-slice(slice) # . . push args 51/push-ecx # . . call e8/call parse-hex-int-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0xa, msg) # . . push args 68/push "F - test-parse-hex-int-from-slice-single-digit"/imm32 68/push 0xa/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-parse-hex-int-from-slice-multi-digit: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "34a" b8/copy-to-eax "34a"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = parse-hex-int-from-slice(slice) # . . push args 51/push-ecx # . . call e8/call parse-hex-int-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0x34a, msg) # . . push args 68/push "F - test-parse-hex-int-from-slice-multi-digit"/imm32 68/push 0x34a/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-parse-hex-int-from-slice-0x-prefix: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "0x34" b8/copy-to-eax "0x34"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = parse-hex-int-from-slice(slice) # . . push args 51/push-ecx # . . call e8/call parse-hex-int-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0x34, msg) # . . push args 68/push "F - test-parse-hex-int-from-slice-0x-prefix"/imm32 68/push 0x34/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-parse-hex-int-from-slice-zero: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "0" b8/copy-to-eax "0"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = parse-hex-int-from-slice(slice) # . . push args 51/push-ecx # . . call e8/call parse-hex-int-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0, msg) # . . push args 68/push "F - test-parse-hex-int-from-slice-zero"/imm32 68/push 0/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-parse-hex-int-from-slice-0-prefix: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "03" b8/copy-to-eax "03"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = parse-hex-int-from-slice(slice) # . . push args 51/push-ecx # . . call e8/call parse-hex-int-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0x3, msg) # . . push args 68/push "F - test-parse-hex-int-from-slice-0-prefix"/imm32 68/push 0x3/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-parse-hex-int-from-slice-negative: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = "-03" b8/copy-to-eax "-03"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var slice/ecx: slice = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # eax = parse-hex-int-from-slice(slice) # . . push args 51/push-ecx # . . call e8/call parse-hex-int-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, -3, msg) # . . push args 68/push "F - test-parse-hex-int-from-slice-negative"/imm32 68/push -3/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return hex-digit?: # c: byte -> result/eax: boolean # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx # ecx = c 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # return false if c < '0' 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x30/imm32 # compare ecx 7c/jump-if-< $hex-digit?:false/disp8 # return true if c <= '9' 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x39/imm32 # compare ecx 7e/jump-if-<= $hex-digit?:true/disp8 # drop case 25/and-eax-with 0x5f/imm32 # return false if c > 'f' 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x66/imm32 # compare ecx 7f/jump-if-> $hex-digit?:false/disp8 # return true if c >= 'a' 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x61/imm32 # compare ecx 7d/jump-if->= $hex-digit?:true/disp8 # otherwise return false $hex-digit?:false: b8/copy-to-eax 0/imm32/false eb/jump $hex-digit?:end/disp8 $hex-digit?:true: b8/copy-to-eax 1/imm32/true $hex-digit?:end: # . restore registers 59/pop-to-ecx # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-hex-below-0: # eax = hex-digit?(0x2f) # . . push args 68/push 0x2f/imm32 # . . call e8/call hex-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0, msg) # . . push args 68/push "F - test-hex-below-0"/imm32 68/push 0/imm32/false 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return test-hex-0-to-9: # eax = hex-digit?(0x30) # . . push args 68/push 0x30/imm32 # . . call e8/call hex-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-hex-at-0"/imm32 68/push 1/imm32/true 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # eax = hex-digit?(0x39) # . . push args 68/push 0x39/imm32 # . . call e8/call hex-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-hex-at-9"/imm32 68/push 1/imm32/true 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return test-hex-above-9-to-a: # eax = hex-digit?(0x3a) # . . push args 68/push 0x3a/imm32 # . . call e8/call hex-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0, msg) # . . push args 68/push "F - test-hex-above-9-to-a"/imm32 68/push 0/imm32/false 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return test-hex-a-to-f: # eax = hex-digit?(0x61) # . . push args 68/push 0x61/imm32 # . . call e8/call hex-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-hex-at-a"/imm32 68/push 1/imm32/true 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # eax = hex-digit?(0x66) # . . push args 68/push 0x66/imm32 # . . call e8/call hex-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-hex-at-f"/imm32 68/push 1/imm32/true 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return test-hex-above-f: # eax = hex-digit?(0x67) # . . push args 68/push 0x67/imm32 # . . call e8/call hex-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0, msg) # . . push args 68/push "F - test-hex-above-f"/imm32 68/push 0/imm32/false 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return from-hex-char: # in/eax: byte -> out/eax: nibble $from-hex-char:check0: # if (eax < '0') goto abort 3d/compare-eax-with 0x30/imm32/0 7c/jump-if-< $from-hex-char:abort/disp8 $from-hex-char:check1: # if (eax > 'f') goto abort 3d/compare-eax-with 0x66/imm32/f 7f/jump-if-> $from-hex-char:abort/disp8 $from-hex-char:check2: # if (eax > '9') goto next check 3d/compare-eax-with 0x39/imm32/9 7f/jump-if-> $from-hex-char:check3/disp8 $from-hex-char:digit: # return eax - '0' 2d/subtract-from-eax 0x30/imm32/0 c3/return $from-hex-char:check3: # if (eax < 'a') goto abort 3d/compare-eax-with 0x61/imm32/a 7c/jump-if-< $from-hex-char:abort/disp8 $from-hex-char:letter: # return eax - ('a'-10) 2d/subtract-from-eax 0x57/imm32/a-10 c3/return $from-hex-char:abort: (abort "invalid hex char") # never gets here # . . vim:nowrap:textwidth=0