From 22c09056b2a3b870a468f3d0b896f2f913a059e7 Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Tue, 8 Nov 2022 21:59:38 +0200 Subject: Update assembler --- assembler/gcd-x86-linux.s | 138 --------------------------------- assembler/gcd-x86-solaris.s | 142 ---------------------------------- assembler/gcd-x86_64-linux.s | 126 ------------------------------ gcd-amd64.S | 161 ++++++++++++++++++++++++++++++++++++++ gcd-x86.S | 178 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 339 insertions(+), 406 deletions(-) delete mode 100644 assembler/gcd-x86-linux.s delete mode 100644 assembler/gcd-x86-solaris.s delete mode 100644 assembler/gcd-x86_64-linux.s create mode 100644 gcd-amd64.S create mode 100644 gcd-x86.S diff --git a/assembler/gcd-x86-linux.s b/assembler/gcd-x86-linux.s deleted file mode 100644 index aa46fd3..0000000 --- a/assembler/gcd-x86-linux.s +++ /dev/null @@ -1,138 +0,0 @@ -# This program is for Linux on Intel x86 arch (32 bits). -# Written for GNU Assembler (as) with AT&T syntax - -# To make an executable binary: -# gcc -nostdlib gcd-x86-linux.s -o gcd-x86-linux -# or -# as gcd-x86-linux.s -o gcd-x86-linux.o && \ -# ld gcd-x86-linux.o -o gcd-x86-linux - -# On 64 bits system: -# gcc -m32 -nostdlib gcd-x86-linux.s -o gcd-x86-linux -# or -# as --32 gcd-x86-linux.s -o gcd-x86-linux.o && \ -# ld -melf_i386 gcd-x86-linux.o -o gcd-x86-linux -# -# To run: -# ./gcd-x86-linux 11 22 33 121 792 -# (output should be 11) - - -.data - -# Buffer for output: -buffer: - .space 32 # enough for 32 bits integer -buf_end: - .byte 10 # new line - - -.text -.globl _start - - -# GCD of two numbers. -# input: eax, ebx - two numbers -# output: eax - GCD -# uses: eax, ebx, edx -gcd2: - and %ebx, %ebx # is %ebx == 0 ? - jz gcd2_exit # %ebx == 0, go to exit and return %eax (GCD) - xor %edx, %edx # set %edx = 0 */ - div %ebx # divide: %edx:%eax / %ebx, actually: %eax / %ebx - mov %ebx, %eax # drop quotient in %eax and keep previous %ebx in %eax - mov %edx, %ebx # put remainder in %ebx - jmp gcd2 -gcd2_exit: - ret - - - -# Print an unsigned integer in eax. -# input: eax - unsigned integer to print -# uses: eax, ebx, ecx, edx, edi, buffer -print: - mov $10, %ecx # set %ecx = 10 (radix) - mov $buf_end, %edi - -next_digit: - xor %edx, %edx # set %edx = 0 - div %ecx # divide: %edx:%eax / %ecx, actually: %eax / %ecx - # %edx is a remainder (0-9), it fits into %dl - add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1' - dec %edi # put remainders going from the end of the buffer - mov %dl, (%edi) - # now eax is a quotient - and %eax, %eax # is quotient == 0 ? - jnz next_digit # quotient is not 0, go on - - # printing the number: - mov $4, %eax # syscall `write' - mov $1, %ebx # write to stdout - mov %edi, %ecx # first character to write - mov $buf_end, %edx - sub %edi, %edx # edx is a number of characters to write (buf_end - edi) - inc %edx # + new line - int $0x80 # do syscall (print the number) - - ret - - -# Convert string into unsigned integer -# input: esi - pointer to string -# output: ebx - unsigned integer -# uses: eax, ebx, ecx, edi, direction flag -str2uint: - xor %ecx, %ecx # it will be the string length - dec %ecx # ecx = -1 != 0 for repne - xor %eax, %eax # search for 0 (%eax = %al = 0) - mov %esi, %edi - cld # Search forward (std - backward) - repne scasb # search for 0 (in %al), incrementing edi, decrementing ecx - not %ecx # invert ecx to have the string length - dec %ecx # minus ending zero - - xor %ebx, %ebx -str2uint_loop: - lodsb # going forward from esi - # HINT: assert '0' <= al <= '9' - lea (%ebx, %ebx, 4), %ebx # ebx = 4*ebx + ebx = 5*ebx ;-) - lea -48(%eax, %ebx, 2), %ebx # ebx = 2*ebx + %eax - 48 - # ebx is multiplied by 10 each iteration, - # eax-48 will be multiplied at the next iteration ;-) - loop str2uint_loop - ret - - - -# Entry point for the program -_start: - - # Access command line, see: - # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html - # Example: ./gcd-x86-linux 11 22 33 - pop %ecx # Get the number of command-line options (4) - pop %esi # Get the pointer to the program name (./gcd-x86-linux), - dec %ecx # minus program name - jz exit # no arguments are given - exiting - - xor %eax, %eax -gcd_loop: - pop %esi # get next command line argument - # Well, we used all registers, now we DO NEED stack :-) - push %ecx # save argument counter - push %eax # save current GCD - call str2uint # convert string at esi to integer at ebx - pop %eax # restore current GCD - call gcd2 # gcd of eax and ebx (returned by str2uint) - # now eax is a GCD - pop %ecx # restore argument counter - loop gcd_loop - - call print # print eax with GCD - -exit: - mov $1, %eax # exit syscall - xor %ebx, %ebx # exit code = 0 - int $0x80 - diff --git a/assembler/gcd-x86-solaris.s b/assembler/gcd-x86-solaris.s deleted file mode 100644 index 50a93f2..0000000 --- a/assembler/gcd-x86-solaris.s +++ /dev/null @@ -1,142 +0,0 @@ -# This program is for Solaris 11 on Intel x86 arch (32 bits). -# Written for GNU Assembler (as) with AT&T syntax - -# To make an executable binary: -# gcc -nostdlib gcd-x86-solaris.s -o gcd-x86-solaris -# or -# as gcd-x86-solaris.s -o gcd-x86-solaris.o && \ -# ld gcd-x86-solaris.o -o gcd-x86-solaris - -# On 64 bits system: -# gcc -m32 -nostdlib gcd-x86-solaris.s -o gcd-x86-solaris -# or -# as --32 gcd-x86-solaris.s -o gcd-x86-solaris.o && \ -# ld -melf_i386 gcd-x86-solaris.o -o gcd-x86-solaris -# -# To run: -# ./gcd-x86-solaris 11 22 33 121 792 -# (output should be 11) - - -.data - -# Buffer for output: -buffer: - .space 32 # enough for 32 bits integer -buf_end: - .byte 10 # new line - - -.text -.globl _start - - -# GCD of two numbers. -# input: eax, ebx - two numbers -# output: eax - GCD -# uses: eax, ebx, edx -gcd2: - and %ebx, %ebx # is %ebx == 0 ? - jz gcd2_exit # %ebx == 0, go to exit and return %eax (GCD) - xor %edx, %edx # set %edx = 0 */ - div %ebx # divide: %edx:%eax / %ebx, actually: %eax / %ebx - mov %ebx, %eax # drop quotient in %eax and keep previous %ebx in %eax - mov %edx, %ebx # put remainder in %ebx - jmp gcd2 -gcd2_exit: - ret - - - -# Print an unsigned integer in eax. -# input: eax - unsigned integer to print -# uses: eax, ebx, ecx, edx, edi, buffer -print: - mov $10, %ecx # set %ecx = 10 (radix) - mov $buf_end, %edi - -next_digit: - xor %edx, %edx # set %edx = 0 - div %ecx # divide: %edx:%eax / %ecx, actually: %eax / %ecx - # %edx is a remainder (0-9), it fits into %dl - add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1' - dec %edi # put remainders going from the end of the buffer - mov %dl, (%edi) - # now eax is a quotient - and %eax, %eax # is quotient == 0 ? - jnz next_digit # quotient is not 0, go on - - # printing the number: - mov $4, %eax # syscall `write' - mov $buf_end, %edx - sub %edi, %edx # edx is a number of characters to write (buf_end - edi) - inc %edx # + new line - push %edx - push %edi # first character to write - push $1 # write to stdout - push $0 # dummy - int $0x91 # do syscall (print the number) - add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!) - - ret - - -# Convert string into unsigned integer -# input: esi - pointer to string -# output: ebx - unsigned integer -# uses: eax, ebx, ecx, edi, direction flag -str2uint: - xor %ecx, %ecx # it will be the string length - dec %ecx # ecx = -1 != 0 for repne - xor %eax, %eax # search for 0 (%eax = %al = 0) - mov %esi, %edi - cld # Search forward (std - backward) - repne scasb # search for 0 (in %al), incrementing edi, decrementing ecx - not %ecx # invert ecx to have the string length - dec %ecx # minus ending zero - - xor %ebx, %ebx -str2uint_loop: - lodsb # going forward from esi - # HINT: assert '0' <= al <= '9' - lea (%ebx, %ebx, 4), %ebx # ebx = 4*ebx + ebx = 5*ebx ;-) - lea -48(%eax, %ebx, 2), %ebx # ebx = 2*ebx + %eax - 48 - # ebx is multiplied by 10 each iteration, - # eax-48 will be multiplied at the next iteration ;-) - loop str2uint_loop - ret - - - -# Entry point for the program -_start: - - # Access command line, see: - # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html - # Example: ./gcd-x86-solaris 11 22 33 - pop %ecx # Get the number of command-line options (4) - pop %esi # Get the pointer to the program name (./gcd-x86-solaris), - dec %ecx # minus program name - jz exit # no arguments are given - exiting - - xor %eax, %eax -gcd_loop: - pop %esi # get next command line argument - # Well, we used all registers, now we DO NEED stack :-) - push %ecx # save argument counter - push %eax # save current GCD - call str2uint # convert string at esi to integer at ebx - pop %eax # restore current GCD - call gcd2 # gcd of eax and ebx (returned by str2uint) - # now eax is a GCD - pop %ecx # restore argument counter - loop gcd_loop - - call print # print eax with GCD - -exit: - mov $1, %eax # exit syscall - push $0 # exit code = 0 - push $0 # dummy - int $0x91 - diff --git a/assembler/gcd-x86_64-linux.s b/assembler/gcd-x86_64-linux.s deleted file mode 100644 index ad92477..0000000 --- a/assembler/gcd-x86_64-linux.s +++ /dev/null @@ -1,126 +0,0 @@ -# This program is for Linux on Intel x86_64 arch (64 bits). -# Written for GNU Assembler (as) with AT&T syntax - -# To make an executable binary: -# gcc -nostdlib gcd-x86_64-linux.s -o gcd-x86_64-linux -# or -# as gcd-x86_64-linux.s -o gcd-x86_64-linux.o && \ -# ld gcd-x86_64-linux.o -o gcd-x86_64-linux - - -.data - -# Buffer for output: -buffer: - .space 64 # enough for 64 bits integer -buf_end: - .byte 10 # new line - - -.text -.globl _start - - -# GCD of two numbers. -# input: rax, rbx - two numbers -# output: rax - GCD -# uses: rax, rbx, rdx -gcd2: - and %rbx, %rbx # is %rbx == 0 ? - jz gcd2_exit # %rbx == 0, go to exit and return %rax (GCD) - xor %rdx, %rdx # set %rdx = 0 */ - div %rbx # divide: %rdx:%rax / %rbx, actually: %rax / %rbx - mov %rbx, %rax # drop quotient in %rax and keep prrvious %rbx in %rax - mov %rdx, %rbx # put remainder in %rbx - jmp gcd2 -gcd2_exit: - ret - - - -# Print an unsigned integer in rax. -# input: rax - unsigned integer to print -# uses: rax, rbx, rcx, rdx, rdi, buffer -print: - mov $10, %rcx # set %rcx = 10 (radix) - mov $buf_end, %rsi - -next_digit: - xor %rdx, %rdx # set %rdx = 0 - div %rcx # divide: %rdx:%rax / %rcx, actually: %rax / %rcx - # %rdx is a remainder (0-9), it fits into %dl - add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1' - dec %rsi # put remainders going from the end of the buffer - mov %dl, (%rsi) - # now rax is a quotient - and %rax, %rax # is quotient == 0 ? - jnz next_digit # quotient is not 0, go on - - # printing the number: - mov $1, %rax # syscall `write' - mov $1, %rdi # write to stdout - mov $buf_end, %rdx - sub %rsi, %rdx # rdx is a number of characters to write (buf_end - rsi) - inc %rdx # + new line - syscall # do syscall (print the number at rsi) - - ret - - -# Convert string into unsigned integer -# input: rsi - pointer to string -# output: rbx - unsigned integer -# uses: rax, rbx, rcx, rdi, direction flag -str2uint: - xor %rcx, %rcx # it will be the string length - dec %rcx # rcx = -1 != 0 for repne - xor %rax, %rax # search for 0 (%rax = %al = 0) - mov %rsi, %rdi - cld # Search forward (std - backward) - repne scasb # search for 0 (in %al), incrementing rdi, decrementing rcx - not %rcx # invert rcx to have the string length - dec %rcx # minus ending zero - - xor %rbx, %rbx -str2uint_loop: - lodsb # going forward from rsi - # HINT: assert '0' <= al <= '9' - lea (%rbx, %rbx, 4), %rbx # rbx = 4*rbx + rbx = 5*rbx ;-) - lea -48(%rax, %rbx, 2), %rbx # rbx = 2*rbx + %rax - 48 - # rbx is multiplied by 10 each iteration, - # rax-48 will be multiplied at the next iteration ;-) - loop str2uint_loop - ret - - - -# Entry point for the program -_start: - - # Access command line, see: - # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html - # Example: ./gcd-x86_64-linux 11 22 33 - pop %rcx # Get the number of command-line options (4) - pop %rsi # Get the pointer to the program name (./gcd-x86_64-linux), - dec %rcx # minus program name - jz exit # no arguments are given - exiting - - xor %rax, %rax -gcd_loop: - pop %rsi # get next command line argument - mov %rcx, %r8 # save argument counter - mov %rax, %r9 # save current GCD - call str2uint # convert string at rsi to integer at rbx - mov %r9, %rax # restore current GCD - call gcd2 # gcd of rax and rbx (returned by str2uint) - # now rax is a GCD - mov %r8, %rcx # restore argument counter - loop gcd_loop - - call print # print rax with GCD - -exit: - mov $60, %rax # exit syscall - xor %rdi, %rdi # exit code = 0 - syscall - diff --git a/gcd-amd64.S b/gcd-amd64.S new file mode 100644 index 0000000..16be38f --- /dev/null +++ b/gcd-amd64.S @@ -0,0 +1,161 @@ +# This program is for amd64 arch (64 bits) running Linux, Solaris or FreeBSD. +# Written for GNU Assembler (as) with AT&T syntax +# +# Synopsis: +# +# $ gcc -nostdlib [-D OS=LINUX] gcd-amd64.S -o gcd-amd64-linux +# or +# $ cpp [-D OS=LINUX] gcd-amd64.S | as -o gcd-amd64-linux.o \ +# && ld gcd-amd64-linux.o -o gcd-amd64-linux +# +# +# $ gcc -nostdlib -D OS=SOLARIS gcd-amd64.S -o gcd-amd64-solaris +# or +# $ cpp -D OS=SOLARIS gcd-amd64.S | gas -64 -o gcd-amd64-solaris.o \ +# && gld -m elf_x86_64_sol2 gcd-amd64-solaris.o -o gcd-amd64-solaris +# +# $ clang -nostdlib -D OS=FREEBSD gcd-amd64.S -o gcd-amd64-freebsd +# + +#define LINUX 1 +#define SOLARIS 2 +#define FREEBSD 3 + +#ifndef OS +#define OS LINUX +#endif + + +.data + +# Buffer for output: +buffer: + .space 64 # enough for a 64-bit integer +buf_end: + .byte 10 # new line + + +.text +.globl _start + + +# GCD of two numbers. +# input: rax, rbx - two numbers +# output: rax - GCD +# uses: rax, rbx, rdx +gcd2: + and %rbx, %rbx # is %rbx == 0 ? + jz gcd2_exit # %rbx == 0, go to exit and return %rax (GCD) + xor %rdx, %rdx # set %rdx = 0 + div %rbx # divide: %rdx:%rax / %rbx, actually: %rax / %rbx + mov %rbx, %rax # drop quotient in %rax and keep prrvious %rbx in %rax + mov %rdx, %rbx # put remainder in %rbx + jmp gcd2 +gcd2_exit: + ret + + + +# Print an unsigned integer in rax. +# input: rax - unsigned integer to print +# uses: rax, rbx, rcx, rdx, rdi, buffer +print: + mov $10, %rcx # set %rcx = 10 (radix) + mov $buf_end, %rsi + +next_digit: + xor %rdx, %rdx # set %rdx = 0 + div %rcx # divide: %rdx:%rax / %rcx, actually: %rax / %rcx + # %rdx is a remainder (0-9), it fits into %dl + add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1' + dec %rsi # put remainders going from the end of the buffer + mov %dl, (%rsi) + # now rax is a quotient + and %rax, %rax # is quotient == 0 ? + jnz next_digit # quotient is not 0, go on + + # printing the number: +#if OS == LINUX + mov $1, %rax # syscall `write' +#elif OS == SOLARIS + mov $4, %rax # syscall `write' +#elif OS == FREEBSD + mov $4, %rax # syscall `write' +#else +#error bad OS. +#endif + mov $1, %rdi # write to stdout + mov $buf_end, %rdx + sub %rsi, %rdx # rdx is a number of characters to write (buf_end - rsi) + inc %rdx # + new line + syscall # do syscall (print the number at rsi) + ret + + +# Convert string into unsigned integer +# input: rsi - pointer to string +# output: rbx - unsigned integer +# uses: rax, rbx, rcx, rdi, direction flag +str2uint: + xor %rcx, %rcx # it will be the string length + dec %rcx # rcx = -1 != 0 for repne + xor %rax, %rax # search for 0 (%rax = %al = 0) + mov %rsi, %rdi + cld # Search forward (std - backward) + repne scasb # search for 0 (in %al), incrementing rdi, decrementing rcx + not %rcx # invert rcx to have the string length + dec %rcx # minus ending zero + + xor %rbx, %rbx +str2uint_loop: + lodsb # going forward from rsi + # HINT: assert '0' <= al <= '9' + lea (%rbx, %rbx, 4), %rbx # rbx = 4*rbx + rbx = 5*rbx ;-) + lea -48(%rax, %rbx, 2), %rbx # rbx = 2*rbx + %rax - 48 + # rbx is multiplied by 10 each iteration, + # rax-48 will be multiplied at the next iteration ;-) + loop str2uint_loop + ret + + + +# Entry point for the program +_start: + + # Access command line. + # Example: ./gcd-amd64-linux 11 22 33 +#if OS == FREEBSD + mov %rdi, %rsp +#endif + pop %rcx # Get the number of command-line options (4) + pop %rsi # Get the pointer to the program name (./gcd-amd64-linux), + dec %rcx # minus program name + jz exit # no arguments are given - exiting + + xor %rax, %rax +gcd_loop: + pop %rsi # get next command line argument + mov %rcx, %r8 # save argument counter + mov %rax, %r9 # save current GCD + call str2uint # convert string at rsi to integer at rbx + mov %r9, %rax # restore current GCD + call gcd2 # gcd of rax and rbx (returned by str2uint) + # now rax is a GCD + mov %r8, %rcx # restore argument counter + loop gcd_loop + + call print # print rax with GCD + +exit: +#if OS == LINUX + mov $60, %rax # exit syscall +#elif OS == SOLARIS + mov $1, %rax # exit syscall +#elif OS == FREEBSD + mov $1, %rax # exit syscall +#else +#error bad OS. +#endif + xor %rdi, %rdi # exit code = 0 + syscall + diff --git a/gcd-x86.S b/gcd-x86.S new file mode 100644 index 0000000..c8d6c79 --- /dev/null +++ b/gcd-x86.S @@ -0,0 +1,178 @@ +# This program is for Intel x86 arch (32 bits) running Linux, Solaris or FreeBSD. +# Written for GNU Assembler (as) with AT&T syntax +# +# Synopsis: +# +# $ gcc -nostdlib -m32 [-D OS=LINUX] gcd-x86.S -o gcd-x86-linux +# or +# $ cpp [-D OS=LINUX] gcd-x86.S | as -32 -o gcd-x86-linux.o \ +# && ld -m elf_i386 gcd-x86-linux.o -o gcd-x86-linux +# +# +# $ gcc -nostdlib -m32 -D OS=SOLARIS gcd-x86.S -o gcd-x86-solaris +# or +# $ cpp -D OS=SOLARIS gcd-x86.S | gas -32 -o gcd-x86-solaris.o \ +# && gld -m elf_i386_sol2 gcd-x86-solaris.o -o gcd-x86-solaris +# +# +# $ clang -nostdlib -m32 -D OS=FREEBSD gcd-x86.S -o gcd-x86-freebsd +# + +#define LINUX 1 +#define SOLARIS 2 +#define FREEBSD 3 + +#ifndef OS +#define OS LINUX +#endif + +.data + +# Buffer for output: +buffer: + .space 32 # enough for a 32-bit integer +buf_end: + .byte 10 # new line + + +.text +.globl _start + + +# GCD of two numbers. +# input: eax, ebx - two numbers +# output: eax - GCD +# uses: eax, ebx, edx +gcd2: + and %ebx, %ebx # is %ebx == 0 ? + jz gcd2_exit # %ebx == 0, go to exit and return %eax (GCD) + xor %edx, %edx # set %edx = 0 + div %ebx # divide: %edx:%eax / %ebx, actually: %eax / %ebx + mov %ebx, %eax # drop quotient in %eax and keep previous %ebx in %eax + mov %edx, %ebx # put remainder in %ebx + jmp gcd2 +gcd2_exit: + ret + + + +# Print an unsigned integer in eax. +# input: eax - unsigned integer to print +# uses: eax, ebx, ecx, edx, edi, buffer +print: + mov $10, %ecx # set %ecx = 10 (radix) + mov $buf_end, %edi + +next_digit: + xor %edx, %edx # set %edx = 0 + div %ecx # divide: %edx:%eax / %ecx, actually: %eax / %ecx + # %edx is a remainder (0-9), it fits into %dl + add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1' + dec %edi # put remainders going from the end of the buffer + mov %dl, (%edi) + # now eax is a quotient + and %eax, %eax # is quotient == 0 ? + jnz next_digit # quotient is not 0, go on + + # printing the number: + mov $buf_end, %edx + sub %edi, %edx # edx is a number of characters to write (buf_end - edi) + inc %edx # + new line +#if OS == LINUX + mov $4, %eax # syscall `write' + mov $1, %ebx # write to stdout + mov %edi, %ecx # first character to write + int $0x80 # do syscall (print the number) +#elif OS == SOLARIS + mov $4, %eax # syscall `write' + push %edx + push %edi # first character to write + push $1 # write to stdout + push $0 # dummy + int $0x91 # do syscall (print the number) + add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!) +#elif OS == FREEBSD + mov $4, %eax # syscall `write' + push %edx + push %edi # first character to write + push $1 # write to stdout + push $0 # dummy + int $0x80 # do syscall (print the number) + add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!) +#else +#error bad OS. +#endif + ret + + +# Convert string into unsigned integer +# input: esi - pointer to string +# output: ebx - unsigned integer +# uses: eax, ebx, ecx, edi, direction flag +str2uint: + xor %ecx, %ecx # it will be the string length + dec %ecx # ecx = -1 != 0 for repne + xor %eax, %eax # search for 0 (%eax = %al = 0) + mov %esi, %edi + cld # Search forward (std - backward) + repne scasb # search for 0 (in %al), incrementing edi, decrementing ecx + not %ecx # invert ecx to have the string length + dec %ecx # minus ending zero + + xor %ebx, %ebx +str2uint_loop: + lodsb # going forward from esi + # HINT: assert '0' <= al <= '9' + lea (%ebx, %ebx, 4), %ebx # ebx = 4*ebx + ebx = 5*ebx ;-) + lea -48(%eax, %ebx, 2), %ebx # ebx = 2*ebx + %eax - 48 + # ebx is multiplied by 10 each iteration, + # eax-48 will be multiplied at the next iteration ;-) + loop str2uint_loop + ret + + + +# Entry point for the program +_start: + + # Access command line. + # Example: ./gcd-x86-linux 11 22 33 + pop %ecx # Get the number of command-line options (4) + pop %esi # Get the pointer to the program name (./gcd-x86-linux), + dec %ecx # minus program name + jz exit # no arguments are given - exiting + + xor %eax, %eax +gcd_loop: + pop %esi # get next command line argument + # Well, we used all registers, now we DO NEED stack :-) + push %ecx # save argument counter + push %eax # save current GCD + call str2uint # convert string at esi to integer at ebx + pop %eax # restore current GCD + call gcd2 # gcd of eax and ebx (returned by str2uint) + # now eax is a GCD + pop %ecx # restore argument counter + loop gcd_loop + + call print # print eax with GCD + +exit: +#if OS == LINUX + mov $1, %eax # exit syscall + xor %ebx, %ebx # exit code = 0 + int $0x80 +#elif OS == SOLARIS + mov $1, %eax # exit syscall + push $0 # exit code = 0 + push $0 # dummy + int $0x91 +#elif OS == FREEBSD + mov $1, %eax # exit syscall + push $0 # exit code = 0 + push $0 # dummy + int $0x80 +#else +#error bad OS. +#endif + -- cgit v1.2.3