summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2022-11-08 21:59:38 +0200
committerIgor Pashev <pashev.igor@gmail.com>2022-11-08 22:09:21 +0200
commit22c09056b2a3b870a468f3d0b896f2f913a059e7 (patch)
treeabe7b3d6ec6e92858ef3b2d7454fc35d6b8e1e23
parentac41f7286588e21b63563151206d0e10ce655ac8 (diff)
downloadgcd-22c09056b2a3b870a468f3d0b896f2f913a059e7.tar.gz
Update assembler
-rw-r--r--assembler/gcd-x86-solaris.s142
-rw-r--r--gcd-amd64.S (renamed from assembler/gcd-x86_64-linux.s)65
-rw-r--r--gcd-x86.S (renamed from assembler/gcd-x86-linux.s)86
3 files changed, 113 insertions, 180 deletions
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/gcd-amd64.S
index ad92477..16be38f 100644
--- a/assembler/gcd-x86_64-linux.s
+++ b/gcd-amd64.S
@@ -1,18 +1,36 @@
-# This program is for Linux on Intel x86_64 arch (64 bits).
+# This program is for amd64 arch (64 bits) running Linux, Solaris or FreeBSD.
# 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
+#
+# 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
-# as gcd-x86_64-linux.s -o gcd-x86_64-linux.o && \
-# ld gcd-x86_64-linux.o -o gcd-x86_64-linux
+# $ 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 64 bits integer
+ .space 64 # enough for a 64-bit integer
buf_end:
.byte 10 # new line
@@ -28,7 +46,7 @@ buf_end:
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 */
+ 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
@@ -57,13 +75,20 @@ next_digit:
jnz next_digit # quotient is not 0, go on
# printing the number:
- mov $1, %rax # syscall `write'
+#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
@@ -97,11 +122,13 @@ str2uint_loop:
# 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
+ # 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-x86_64-linux),
+ pop %rsi # Get the pointer to the program name (./gcd-amd64-linux),
dec %rcx # minus program name
jz exit # no arguments are given - exiting
@@ -120,7 +147,15 @@ gcd_loop:
call print # print rax with GCD
exit:
- mov $60, %rax # exit syscall
+#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/assembler/gcd-x86-linux.s b/gcd-x86.S
index aa46fd3..c8d6c79 100644
--- a/assembler/gcd-x86-linux.s
+++ b/gcd-x86.S
@@ -1,28 +1,36 @@
-# This program is for Linux on Intel x86 arch (32 bits).
+# This program is for Intel x86 arch (32 bits) running Linux, Solaris or FreeBSD.
# Written for GNU Assembler (as) with AT&T syntax
-
-# To make an executable binary:
-# gcc -nostdlib gcd-x86-linux.s -o gcd-x86-linux
+#
+# Synopsis:
+#
+# $ gcc -nostdlib -m32 [-D OS=LINUX] gcd-x86.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
+# $ 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
-# as --32 gcd-x86-linux.s -o gcd-x86-linux.o && \
-# ld -melf_i386 gcd-x86-linux.o -o gcd-x86-linux
+# $ 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
#
-# To run:
-# ./gcd-x86-linux 11 22 33 121 792
-# (output should be 11)
+#
+# $ 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 32 bits integer
+ .space 32 # enough for a 32-bit integer
buf_end:
.byte 10 # new line
@@ -38,7 +46,7 @@ buf_end:
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 */
+ 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
@@ -65,16 +73,35 @@ next_digit:
# 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
+#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
@@ -108,8 +135,7 @@ str2uint_loop:
# Entry point for the program
_start:
- # Access command line, see:
- # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html
+ # 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),
@@ -132,7 +158,21 @@ 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