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
Read a: 6
You typed: 6
Read b: 4
You typed: 4
Błąd w obliczeniach zmiennoprzecinkowych
margor@xeon:
/programowanie/projekty/1asembler> ./main
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?