diff options
Diffstat (limited to 'subx/examples')
-rwxr-xr-x | subx/examples/ex1 | bin | 0 -> 96 bytes | |||
-rw-r--r-- | subx/examples/ex1.1.subx | 20 | ||||
-rw-r--r-- | subx/examples/ex1.2.subx | 20 | ||||
-rwxr-xr-x | subx/examples/ex2 | bin | 0 -> 102 bytes | |||
-rw-r--r-- | subx/examples/ex2.subx | 20 | ||||
-rwxr-xr-x | subx/examples/ex3 | bin | 0 -> 119 bytes | |||
-rw-r--r-- | subx/examples/ex3.subx | 35 | ||||
-rwxr-xr-x | subx/examples/ex4 | bin | 0 -> 171 bytes | |||
-rw-r--r-- | subx/examples/ex4.subx | 41 | ||||
-rwxr-xr-x | subx/examples/ex5 | bin | 0 -> 138 bytes | |||
-rw-r--r-- | subx/examples/ex5.subx | 45 | ||||
-rwxr-xr-x | subx/examples/ex6 | bin | 0 -> 166 bytes | |||
-rw-r--r-- | subx/examples/ex6.subx | 36 | ||||
-rwxr-xr-x | subx/examples/ex7 | bin | 0 -> 156 bytes | |||
-rw-r--r-- | subx/examples/ex7.subx | 64 | ||||
-rwxr-xr-x | subx/examples/ex8 | bin | 0 -> 313 bytes | |||
-rw-r--r-- | subx/examples/ex8.subx | 99 | ||||
-rwxr-xr-x | subx/examples/ex9 | bin | 0 -> 144 bytes | |||
-rw-r--r-- | subx/examples/ex9.subx | 61 |
19 files changed, 441 insertions, 0 deletions
diff --git a/subx/examples/ex1 b/subx/examples/ex1 new file mode 100755 index 00000000..f3c9730d --- /dev/null +++ b/subx/examples/ex1 Binary files differdiff --git a/subx/examples/ex1.1.subx b/subx/examples/ex1.1.subx new file mode 100644 index 00000000..1cbe5dc1 --- /dev/null +++ b/subx/examples/ex1.1.subx @@ -0,0 +1,20 @@ +## first program: same as https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html +# Just return 42. +# +# To run: +# $ subx translate ex1.1.subx ex1 +# $ subx run ex1 +# Expected result: +# $ echo $? +# 42 + +== 0x08048054 # code segment, after leaving room for ELF header +# opcode ModR/M SIB displacement immediate +# instruction mod, reg, Reg/Mem bits scale, index, base +# 1-3 bytes 0/1 byte 0/1 byte 0/1/2/4 bytes 0/1/2/4 bytes + bb 2a 00 00 00 # copy 0x2a (42) to EBX + # exit(EBX) + b8 01 00 00 00 # copy 1 to EAX + cd 80 # int 80h + +# vim:ft=subx diff --git a/subx/examples/ex1.2.subx b/subx/examples/ex1.2.subx new file mode 100644 index 00000000..2652037a --- /dev/null +++ b/subx/examples/ex1.2.subx @@ -0,0 +1,20 @@ +## first program: same as https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html +# Just return 42. +# +# To run: +# $ subx translate ex1.2.subx ex1 +# $ subx run ex1 +# Expected result: +# $ echo $? +# 42 + +== 0x08048054 # code segment, after leaving room for ELF header +# instruction effective address operand 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 + bb/copy 2a/imm32 # copy 42 to EBX + # exit(EBX) + b8/copy 1/imm32 # copy 1 to EAX + cd/syscall 0x80/imm8 # int 80h + +# vim:ft=subx diff --git a/subx/examples/ex2 b/subx/examples/ex2 new file mode 100755 index 00000000..3bbd979b --- /dev/null +++ b/subx/examples/ex2 Binary files differdiff --git a/subx/examples/ex2.subx b/subx/examples/ex2.subx new file mode 100644 index 00000000..6463132b --- /dev/null +++ b/subx/examples/ex2.subx @@ -0,0 +1,20 @@ +## add 1 and 1, and return the result in the exit code +# +# To run: +# $ subx translate ex2.subx ex2 +# $ subx run ex2 +# Expected result: +# $ echo $? +# 2 + +== 0x08048054 # code segment, after leaving room for ELF header +# instruction effective address operand 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 + bb/copy 1/imm32 # copy 1 to EBX + 81 0/subop/add 3/mod/direct 3/rm32/EBX 1/imm32 # add 1 to EBX + # exit(EBX) + b8/copy 1/imm32 # copy 1 to EAX + cd/syscall 0x80/imm8 # int 80h + +# vim:ft=subx diff --git a/subx/examples/ex3 b/subx/examples/ex3 new file mode 100755 index 00000000..aa209b92 --- /dev/null +++ b/subx/examples/ex3 Binary files differdiff --git a/subx/examples/ex3.subx b/subx/examples/ex3.subx new file mode 100644 index 00000000..a4012f92 --- /dev/null +++ b/subx/examples/ex3.subx @@ -0,0 +1,35 @@ +## add the first 10 numbers, and return the result in the exit code +# +# To run: +# $ subx translate ex3.subx ex3 +# $ subx run ex3 +# Expected result: +# $ echo $? +# 55 + +== 0x08048054 # code segment, after leaving room for ELF header +# instruction effective address operand 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 + # result: EBX = 0 + bb/copy 0/imm32 # copy 0 to EBX + # counter: ECX = 1 + b9/copy 1/imm32 # copy 1 to ECX + +$loop: + # while (counter <= 10) + 81 7/subop/compare 3/mod/direct 1/rm32/ECX 0xa/imm32 # compare ECX, 10/imm + 7f/jump-if $exit/disp8 # jump-if-greater $exit + # result += counter + 01/add 3/mod/direct 3/rm32/EBX 1/r32/ECX # add ECX to EBX + # ++counter + 81 0/subop/add 3/mod/direct 1/rm32/ECX 1/imm32 # add 1 to ECX + # loop + eb/jump $loop/disp8 # jump $loop + +$exit: + # exit(EBX) + b8/copy 1/imm32 # copy 1 to EAX + cd/syscall 0x80/imm8 # int 80h + +# vim:ft=subx:nowrap diff --git a/subx/examples/ex4 b/subx/examples/ex4 new file mode 100755 index 00000000..7721c94b --- /dev/null +++ b/subx/examples/ex4 Binary files differdiff --git a/subx/examples/ex4.subx b/subx/examples/ex4.subx new file mode 100644 index 00000000..cd7003d3 --- /dev/null +++ b/subx/examples/ex4.subx @@ -0,0 +1,41 @@ +## read a character from stdin, save it to a global, write it to stdout +# +# To run: +# $ subx translate ex4.subx ex4 +# $ subx run ex4 + +== 0x08048074 # code segment, after leaving room for ELF header and segment headers +# instruction effective address operand 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 + + ## read(stdin, x, 1) + # fd = 0 (stdin) + bb/copy 0/imm32 # copy 0 to EBX + # initialize x (location to write result to) + b9/copy 0x080490a7/imm32 # copy to ECX + # size = 1 character + ba/copy 1/imm32 # copy 1 to EDX + # read(fd, x, size) + b8/copy 3/imm32 # copy 3 to EAX + cd/syscall 0x80/imm8 # int 80h + + ## write(stdout, x, 1) + # fd = 1 (stdout) + bb/copy 1/imm32 # copy 1 to EBX + # initialize x (location to read from) + b9/copy 0x080490a7/imm32 # copy to ECX + # size = 1 character + ba/copy 1/imm32 # copy 1 to EDX + # write(fd, x, size) + b8/copy 4/imm32 # copy 4 to EAX + cd/syscall 0x80/imm8 # int 80h + + ## exit(EBX) + b8/copy 1/imm32 # copy 1 to EAX + cd/syscall 0x80/imm8 # int 80h + +== 0x080490a7 # data segment +00 00 00 00 # space for read() to write to + +# vim:ft=subx:nowrap diff --git a/subx/examples/ex5 b/subx/examples/ex5 new file mode 100755 index 00000000..536ddcd6 --- /dev/null +++ b/subx/examples/ex5 Binary files differdiff --git a/subx/examples/ex5.subx b/subx/examples/ex5.subx new file mode 100644 index 00000000..e4a2db81 --- /dev/null +++ b/subx/examples/ex5.subx @@ -0,0 +1,45 @@ +## read a character from stdin, save it to a local on the stack, write it to stdout +# +# To run: +# $ subx translate ex5.subx ex5 +# $ subx run ex5 + +== 0x08048054 # code segment, after leaving room for ELF header and segment headers +# instruction effective address operand 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 + +## function main + # prolog + 55/push # push EBP + 89/copy 3/mod/direct 5/rm32/EBP 4/r32/ESP # copy ESP to EBP + # allocate x on the stack + 81 5/subop/subtract 3/mod/direct 4/rm32/ESP 4/imm32 # subtract 4 bytes from ESP + + ## read(stdin, x, 1) + # fd = 0 (stdin) + bb/copy 0/imm32 # copy 0 to EBX + # initialize x (location to write result to) + 89/copy 3/mod/direct 1/rm32/ECX 5/r32/EBP # copy EBP to ECX + # size = 1 character + ba/copy 1/imm32 # copy 1 to EDX + # read(fd, x, size) + b8/copy 3/imm32 # copy 3 to EAX + cd/syscall 0x80/imm8 # int 80h + + ## write(stdout, x, 1) + # fd = 1 (stdout) + bb/copy 1/imm32 # copy 1 to EBX + # initialize x (location to read from) + 89/copy 3/mod/direct 1/rm32/ECX 5/r32/EBP # copy EBP to ECX + # size = 1 character + ba/copy 1/imm32 # copy 1 to EDX + # write(fd, x, size) + b8/copy 4/imm32 # copy 4 to EAX + cd/syscall 0x80/imm8 # int 80h + + ## exit(EBX) + b8/copy 1/imm32 # copy 1 to EAX + cd/syscall 0x80/imm8 # int 80h + +# vim:ft=subx:nowrap diff --git a/subx/examples/ex6 b/subx/examples/ex6 new file mode 100755 index 00000000..b897bc05 --- /dev/null +++ b/subx/examples/ex6 Binary files differdiff --git a/subx/examples/ex6.subx b/subx/examples/ex6.subx new file mode 100644 index 00000000..4c75c617 --- /dev/null +++ b/subx/examples/ex6.subx @@ -0,0 +1,36 @@ +## print out a (global variable) string to stdout +# +# To run: +# $ subx translate ex6.subx ex6 +# $ subx run ex6 +# Hello, world! + +== 0x08048074 # code segment, after leaving room for ELF header and segment headers +# instruction effective address operand 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 + + ## write(stdout, x, 1) + # fd = 1 (stdout) + bb/copy 1/imm32 # copy 1 to EBX + # initialize x (location to write result to) + b9/copy 0x08049097/imm32 # copy to ECX + # initialize size + ba/copy 0x08049093/imm32 # copy to EDX + 8b/copy 0/mod/indirect 2/rm32/EDX 2/r32/EDX # copy *EDX to EDX + # write(fd, x, size) + b8/copy 4/imm32 # copy 4 to EAX + cd/syscall 0x80/imm8 # int 80h + + ## exit(EBX) + b8/copy 1/imm32 # copy 1 to EAX + cd/syscall 0x80/imm8 # int 80h + +== 0x08049093 # data segment +# size of string +0e 00 00 00 +# string + 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a 00 +# h e l l o , ␣ w o r l d ! newline null + +# vim:ft=subx:nowrap diff --git a/subx/examples/ex7 b/subx/examples/ex7 new file mode 100755 index 00000000..daea2cf4 --- /dev/null +++ b/subx/examples/ex7 Binary files differdiff --git a/subx/examples/ex7.subx b/subx/examples/ex7.subx new file mode 100644 index 00000000..86e018c8 --- /dev/null +++ b/subx/examples/ex7.subx @@ -0,0 +1,64 @@ +## compute the factorial of 5, and return the result in the exit code +# +# To run: +# $ subx translate ex7.subx ex7 +# $ subx run ex7 +# Expected result: +# $ echo $? +# 120 + +== 0x08048054 # code segment, after leaving room for ELF header +# instruction effective address operand 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 + +# main: + # prepare to make a call + 55/push . . . . . . . . # push EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # factorial(5) + 68/push . . . . . . . 5/imm32 # push 5 + e8/call . . . . . . factorial/disp32 + # discard arg + 5a/pop . . . . . . . . # pop into EDX + # clean up after call + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop . . . . . . . . # pop to EBP + + # exit(EAX) + 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX + b8/copy . . . . . . . 1/imm32 # copy 1 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + +# factorial(n) +factorial: + # initialize n + 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 2/r32/EDX 4/disp8 . # copy *(ESP+4) to EDX + # initialize EAX to 1 (base case) + b8/copy . . . . . . . 1/imm32 # copy 1 to EAX + # if (n <= 1) jump exit + 81 7/subop/compare 3/mod/direct 2/rm32/EDX . . . . . 1/imm32 # compare EDX with 1 + 7e/jump-if-<= . . . . . . $factorial:exit/disp8 # jump if <= to $factorial:exit + # EBX: n-1 + 89/copy 3/mod/direct 3/rm32/EBX . . . 2/r32/EDX . . # copy EDX to EBX + 81 5/subop/subtract 3/mod/direct 3/rm32/EBX . . . . . 1/imm32 # subtract 1 from EBX + # prepare call + 55/push . . . . . . . . # push EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # EAX: factorial(n-1) + 53/push . . . . . . . . # push EBX + e8/call . . . . . . factorial/disp32 + # discard arg + 5e/pop . . . . . . . . # pop into ESI + # clean up after call + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop . . . . . . . . # pop to EBP + # refresh n + 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 2/r32/EDX 4/disp8 . # copy *(ESP+4) to EDX + # return n * factorial(n-1) + 0f af/multiply 3/mod/direct 2/rm32/EDX . . . 0/r32/EAX . . # multiply EDX (n) into EAX (factorial(n-1)) + # TODO: check for overflow +$factorial:exit: + c3/return + +# vim:ft=subx:nowrap:so=0 diff --git a/subx/examples/ex8 b/subx/examples/ex8 new file mode 100755 index 00000000..d756271e --- /dev/null +++ b/subx/examples/ex8 Binary files differdiff --git a/subx/examples/ex8.subx b/subx/examples/ex8.subx new file mode 100644 index 00000000..6f8d3979 --- /dev/null +++ b/subx/examples/ex8.subx @@ -0,0 +1,99 @@ +## example showing file syscalls +# Create a file, open it for writing, write a character to it, close it, open +# it for reading, read a character from it, close it, delete it, and return +# the character read. +# +# To run: +# $ subx translate ex8.subx ex8 +# $ subx run ex8 +# Expected result: +# $ echo $? +# 97 + +== 0x08048074 # code segment, after leaving room for ELF header and segment headers +# instruction effective address operand 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 + + ## creat(filename) + bb/copy . . . . . . . 0x08049131/imm32/fname # copy to EBX + b9/copy . . . . . . . 0x180/imm32/fixed-perms # copy 0 to ECX + b8/copy . . . . . . . 8/imm32/creat # copy 8 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + + ## fd = open(filename, O_WRONLY, 0) + bb/copy . . . . . . . 0x08049131/imm32/fname # copy to EBX + b9/copy . . . . . . . 1/imm32/wronly # copy 1 to ECX + ba/copy . . . . . . . 0x180/imm32/fixed-perms # copy 0 to EDX + b8/copy . . . . . . . 5/imm32/open # copy 5 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + # save fd + bb/copy . . . . . . . 0x08049125/imm32/fd # copy to EBX + 89/copy 0/mod/indirect 3/rm32/EBX 0/r32/EAX # copy EAX to *EBX + + ## write(fd, "a", 1) + # load fd + bb/copy . . . . . . . 0x08049125/imm32/fd # copy to EBX + 8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX + # + b9/copy . . . . . . . 0x08049129/imm32/a # copy to ECX + ba/copy . . . . . . . 1/imm32/size # copy 1 to EDX + b8/copy . . . . . . . 4/imm32/write # copy 4 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + + ## close(fd) + # load fd + bb/copy . . . . . . . 0x08049125/imm32/fd # copy to EBX + 8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX + # + b8/copy . . . . . . . 6/imm32/close # copy 6 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + + ## fd = open(filename, O_RDONLY, 0) + bb/copy . . . . . . . 0x08049131/imm32/fname # copy to EBX + b9/copy . . . . . . . 0/imm32/rdonly # copy 0 to ECX + ba/copy . . . . . . . 0x180/imm32/fixed-perms # copy 0 to EDX + b8/copy . . . . . . . 5/imm32/open # copy 5 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + # save fd + bb/copy . . . . . . . 0x08049125/imm32/fd # copy to EBX + 89/copy 0/mod/indirect 3/rm32/EBX 0/r32/EAX # copy EAX to *EBX + + ## read(fd, b, 1) + # load fd + bb/copy . . . . . . . 0x08049125/imm32/fd # copy to EBX + 8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX + # + b9/copy . . . . . . . 0x0804912d/imm32/b # copy to ECX + ba/copy . . . . . . . 1/imm32/size # copy 1 to EDX + b8/copy . . . . . . . 3/imm32/read # copy 3 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + + ## close(fd) + # load fd + bb/copy . . . . . . . 0x08049125/imm32/fd # copy to EBX + 8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX + # + b8/copy . . . . . . . 6/imm32/close # copy 8 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + + ## unlink(filename) + bb/copy . . . . . . . 0x08049131/imm32/fname # copy to EBX + b8/copy . . . . . . . 0xa/imm32/unlink # copy 8 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + + ## exit(b) + # load b + bb/copy . . . . . . . 0x0804912d/imm32/b # copy to EBX + 8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX + # + b8/copy . . . . . . . 1/imm32/exit # copy 1 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + +== 0x08049125 # data segment +00 00 00 00 # fd +61 00 00 00 # a: string to write to file: 'a' +00 00 00 00 # b: space for string read from file +2e 66 6f 6f 00 00 00 00 # filename: '.foo' + +# vim:ft=subx:nowrap:tw& diff --git a/subx/examples/ex9 b/subx/examples/ex9 new file mode 100755 index 00000000..47c79e3c --- /dev/null +++ b/subx/examples/ex9 Binary files differdiff --git a/subx/examples/ex9.subx b/subx/examples/ex9.subx new file mode 100644 index 00000000..9ea547f1 --- /dev/null +++ b/subx/examples/ex9.subx @@ -0,0 +1,61 @@ +# Example reading commandline arguments: compute length of first arg. +# +# To run: +# $ subx translate ex9.subx ex9 +# $ subx run ex9 abc de fghi +# Expected result: +# $ echo $? +# 3 # length of 'abc' +# +# At the start of a SubX program: +# argc: *ESP +# argv[0]: *(ESP+4) +# argv[1]: *(ESP+8) +# ... +# Locals start from ESP-4 downwards. + +== 0x08048054 # code segment, after leaving room for ELF header and segment headers +# instruction effective address operand 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 + # var s = argv[1] (EBX) + 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 3/r32/EBX 8/disp8 . # copy *(ESP+8) to EBX + # call ascii_length(EBX) + # prepare call + 55/push . . . . . . . . # push EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # push args + 53/push . . . . . . . . # push EBX + # call + e8/call . . . . . . ascii_length/disp32 + # discard args + 5a/pop . . . . . . . . # pop into EDX + # clean up after call + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop . . . . . . . . # pop to EBP + + # exit(EAX) + 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX + b8/copy . . . . . . . 1/imm32/exit # copy 1 to EAX + cd/syscall . . . . . . . 0x80/imm8 # int 80h + +ascii_length: # (s) + # initialize s (EDX) + 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 2/r32/EDX 4/disp8 # copy *(ESP+4) to EDX + # var result = 0 (EAX) + b8/copy . . . . . . . 0/imm32 # copy 1 to EAX +$al_loop: + # var c = *s (ECX) + 8a/copy 0/mod/* 2/rm32/EDX . . . 1/r32/ECX . . # copy byte at *EDX to lower byte of ECX + # if c == '\0' break + 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX with 0 + 74/jump-if-zero . . . . . . . $al_ret/disp8 # jump if equal + # ++s + 81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 1/imm32 # add 1 to EDX + # ++result + 81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 1/imm32 # add 1 to EAX + # loop + eb/jump . . . . . . . $al_loop/disp8 # jump $al_loop +$al_ret: + # return (result in EAX) + c3/return |