Główny program: main.asm
section .text ; begin of the code section
global main ; gcc needs that label
; load library
%include "library.asm"
main:
; printf("read a: ")
mov eax, read_a
call print_c_str
; scanf("%d", &a)
call read_c_int ; scanf("%d", EAX)
mov [a], eax
; printf("You typed: %d\n", a)
mov eax, test_str
call print_c_str
mov eax, [a]
call print_c_int
call print_c_nl
; printf("read b: ")
mov eax, read_b
call print_c_str
call read_c_int ; scanf("%d", EAX)
mov [b], eax
; printf("You typed: %d\n", b)
mov eax, test_str
call print_c_str
mov eax, [b]
call print_c_int
call print_c_nl
; Search the greatest common divisor of a and b.
mov eax, [a] ; EAX = a
mov ebx, [b] ; EBX = b
; EDX = c
; while (b != 0) {
; c = a % b;
; a = b;
; b = c;
; }
; GCD: a
cmp ebx, 0
je endwhile
while:
push eax
idiv ebx ; EDX = EAX % EBX
; EAX = EAX div EBX
pop eax
mov eax, ebx ; a = b
mov ebx, edx ; b = c
cmp ebx, 0 ; if(b == 0)
jne while ; jump not equal
endwhile:
; print GCD
push eax
mov eax, print_gcd
call print_c_str
pop eax
call print_c_int ; EAX
call print_c_nl
; exit to C
mov eax, 0
ret
section .bss ; uninitialized data section
a resw 2 ; long a - reserve 2 words (4 bytes)
b resw 2 ; long b
section .data ; initialized data section
read_a db "Read a: ", 0
read_b db "Read b: ", 0
print_gcd db "GCD is: ", 0
test_str db "You typed: ", 0
Plik library.asm
; external libc functions
extern printf
extern puts
extern scanf
; ************************ ;
; * library C procedures * ;
; ************************ ;
print_c_nl: ; puts("");
pusha
push 0
push dword str_empty
call puts ; call C
pop ecx ; pop stack 1 times 4 bytes
pop eax
popa
retn ; return to previous block
; print_string: prints string which pointer is stored in EAX
print_c_str: ; printf("%s", EAX)
pusha
; do: printf("%s", EAX)
push eax ; address of string to printf
push dword str_string ; address of: "%s", 0
call printf ; call C function
pop ecx
pop ecx ; pop stack 2 times 4 bytes
popa
ret ; return to previous block
; print_char: prints char stored in EAX
print_c_char: ; printf("%c", EAX)
pusha
; do: printf("%c", EAX)
push eax ; value of char to print
push dword str_char ; address of: "%c", 0
call printf ; call C function
pop ecx
pop ecx ; pop stack 2 times 4 bytes
popa
ret ; return to previous block
; read_int: scanf("%d", EAX)
read_c_int:
push 0 ; push local integer
push esp
push dword str_int
call scanf ; call C
pop ecx
pop ecx ; pop 8 bytes
pop eax
ret ; return to previous block
; print_c_int: printf("%d", EAX)
print_c_int:
pusha
; do: printf("%d", EAX)
push eax ; value of int to printf
push dword str_int ; address of: "%d", 0
call printf ; call C function
pop ecx
pop ecx ; pop 2 times 4 bytes
popa
ret ; return to previous block
section .data ; initialized data section
str_int db "%d", 0
str_char db "%c", 0
str_string db "%s", 0
str_empty db 0
nl db 0ah
Próbuje skonstruować odpowiednik while i go praktycznie wykorzystać, w tym celu znalazłem chyba najprostszy algorytm do wykorzystania: szukanie NWD dwóch liczb całkowitych, według wikipedii: http://pl.wikipedia.org/wiki/Algorytm_Euklidesa.
Chyba nic prostszego być nie może, a nawet to mi nie działa. Zakładam, że powalona jest pętla while. Program zazwyczaj kończy się błędem obliczeń zmiennoprzecinkowych na przykład:
margor@xeon:/programowanie/projekty/1asembler> ./main/programowanie/projekty/1asembler> ./main
Read a: 6
You typed: 6
Read b: 4
You typed: 4
Błąd w obliczeniach zmiennoprzecinkowych
margor@xeon:
Read a: 6
You typed: 6
Read b: 3
You typed: 3
GCD is: 3
Szukam błędu i nie widzę. Idealnie gdybym mógł obejrzeć w gdb każdy krok tzn. aby mi wyświetlał następną instrukcję jaka zostanie wykonana (znalazłem, że nexti wykonuje następną instrukcję, ale dobrze gdyby ta instrukcja była wyświetlana, analogicznie do step dla C).
Czy zawalona jest logika programu czy też zupełnie inny błąd?