Linux x86 NASM - Podprogram: Wydrukuj dword z EAX

Uczę się więc montażu Linuxa x86 ze składnią NASM (O Boże, nie to znowu, wszyscy myślicie). Próbuję utworzyć podprogram, który po prostu wydrukuje wartość w EAX na standardowe wyjście. Kod działa i kończy się bez błędu, ale nic nie drukuje. Nie mogę zrozumieć dlaczego. Po pierwsze, oto plik, w którym pracuję:

segment .bss
    to_print:   resd 1

segment .text
    global print_eax_val

print_eax_val:                  ;       (top)
    push    dword ebx           ;Stack:  edx
    push    dword ecx           ;        ecx
    push    dword edx           ;        ebx
                                ;       (bot)

    mov     ecx,eax             ;ecx = eax

    mov     [to_print],ecx      ;to_print = ecx

    mov     eax, 4              ;sys_write
    mov     ebx, 1              ;to stdout
    add     ecx, 47             ;add 47 for ASCII numbers
    mov     edx, 2              ;double word = 2 bytes
    int     0x80

    mov     eax, [to_print]     ;eax = original val
    pop     edx                 ;pop the registers back from the stack
    pop     ecx
    pop     ebx                 ;Stack: empty

    ret

Jest to wywoływane z mojego głównego pliku, który wygląda tak (prawdopodobnie nie ma to znaczenia, chyba że brakuje mi czegoś drastycznego).

segment .data
        hello   db      "Hello world!", 0
        newline db      0xA
        len     equ $ - hello
        len2    equ $ - newline

segment .text
        extern print_nl
        extern print_eax_val
        global main

main:
        enter   0,0

        call    print_nl

        mov     eax, 1

        call    print_eax_val

        mov     ebx, 0          ;exit code = 0 (normal)
        mov     eax, 1          ;exit command
        int     0x80            ;ask kernel to quit

print_nl to kolejny podprogram, który definiuje i drukuje nową linię. Uruchomi się pomyślnie i wydrukuje nową linię zgodnie z oczekiwaniami.

Czy problem ma związek z parametrem długości dla mojegosys_write połączenie? Daję mu 2, który ma rozmiar adword, który jest wielkością obuEAX zarejestruj się i mójto_print etykieta, którą zarezerwowałemresd 1. Próbowałem zmienić długość na 1, 4, 8, 16 i 32 z desperacji ... Nic nie działało.

EDYTOWAĆ: Dla każdego, kto się zastanawia, oto jak naprawiłem kod: (wstawię gwiazdki w liniach, które zmieniłem):

segment .bss
    to_print:   resd 1

segment .text
        global print_eax_val

print_eax_val:                      ;       (top)
        push    dword ebx           ;Stack:  edx
        push    dword ecx           ;        ecx
        push    dword edx           ;        ebx
                                    ;       (bot)

        mov     ecx,eax             ;ecx = eax

        mov     [to_print],ecx        ;to_print = ecx

****    add     dword [to_print], 48

        mov     eax, 4              ;sys_write
        mov     ebx, 1              ;to stdout
****    mov     ecx, to_print
        mov     edx, 2
        int     0x80

****    sub     dword [to_print], 48
        mov     eax, [to_print]     ;eax = original val
        pop     edx                 ;pop the registers back from the stack
        pop     ecx
        pop     ebx                 ;Stack: empty

        ret

Gruntownie,ecx musi zawieraćadres bloku, który chcesz wydrukować, NIE samą wartość. Jak zaznaczono w wybranej odpowiedzi, będzie totylko działa, jeśli eax jest w zakresie 0-9.

EDYCJA 2: Byłem trochę zmieszany co do drugiego parametru dla sys_write (tego przechowywanego wedx). Myślę, że odnosi się to po prostu do liczby bajtów. Więc nadword, tak jak użyłem, właściwe byłoby użycie 4, ponieważ podwójne słowo ma 4 bajty lub 32 bity. Zgaduję, że zadziałało, ponieważ x86 jest małym endianem. Tak więc w pamięci wartość szesnastkowato_print wyglądałoby to tak:

90 00 00 00

A przy podanej długości dwóch sys_write pobiera:

90 00

Więc wartość na szczęście nie ulega uszkodzeniu.

Później zmieniłem kod do przechowywaniato_print zamiast bajtu, używającresb 1 i dostęp do niego za pomocąbyte zamiastdword... Tu jest bajt, bo wiem, że nie damto_print wartość powyżej 9.

questionAnswers(2)

yourAnswerToTheQuestion