2017-04-18 1 views
1

Ich habe versucht, ein Assembly-Programm, das eine Nummer nahm, und dann gedruckt. Aber als ich 1 schrieb, schrieb es 4171. Warum und wie kann ich es reparieren? Ich verwende 64-Bit-Assembly, ich habe es mit nasm -f macho64 scanf.asm zusammengebaut, und ich habe es mit gcc -o scanf scanf.o -Wl,-no-pie verbunden. Und ich habe versucht, eckige Klammern um die Zahl im Scan-Makro zu verwenden (für einen Zeiger auf die Variable), aber nasm mach-o hat es nicht erlaubt, also habe ich das nicht gemacht.Assembly Nummer Änderung Fehler

Hier ist mein Code:

; lib.asm 
extern _printf 
extern _scanf 

%macro print 2 

    push rbp 

    mov rdi, %1 
    mov rsi, %2 

    xor rax, rax 

    call _printf 

    pop rbp 

%endmacro 

%macro scan 2 

    push rbp 

    mov rdi, %1 
    mov rsi, %2 

    mov rax, 0 
    call _scanf 

    pop rbp 

%endmacro 

; scanf.asm 

%INCLUDE "lib.asm" 

section .bss 
    number resd 1 
section .text 
    global _main 
_main: 

    print str_out, qst 
    scan int_in, number 

    print ans, number 

exit: 

    mov rax, 0x2000001 
    xor rbx, rbx 
    syscall 

section .data 
    str_out db '%s', 0xa, 0 
    int_in db '%d', 0 
    int_out db '%d', 0xa, 0 


    qst db 'Enter a number: ', 0 

    ans db 'You wrote: %d', 0xa, 0 
+0

Ihr 'print ans, number' scheint die Adresse von' number' auszudrucken, nicht die Nummer selbst. Was passiert, wenn Sie 'print ans, number' durch' movsx rax, dword [number] '' print ans, rax' ersetzen. In diesem Fall sollte 'mov eax, [number]' 'print ans, rax' auch funktionieren. –

+0

Nasm druckt "scanf.asm: 12: Fehler: Mach-O 64-Bit-Format unterstützt keine absoluten 32-Bit-Adressen", wenn ich versuche "movsx rax, dword [Nummer]", und wenn ich versuche "mov rax, [ Nummer]". – SpilledMango

+0

Okay, versuchen Sie es auf diese Weise, dann 'mov rax, [rel number]' zwingt es, relative RIP-Adressierung zu verwenden –

Antwort

2

Das Makro die Antwort zu drucken ist falsch.

print ans, number 

Wenn das Makro, das Sie bekommen würde erweitert wird:

push rbp 

mov rdi, ans  ; RDI = Address of ans 
mov rsi, number ; RSI = Address of number 

xor rax, rax 

call _printf 

pop rbp 

Ich habe die zwei Linien über und ihre Bedeutung kommentiert. Eine Format-Zeichenfolge von 'You wrote: %d' besagt, dass eine Ganzzahl gedruckt werden soll. Sie haben stattdessen die Adresse number übergeben. Um dies zu beheben, holen Sie sich den 32-Bit-Wert von number und legen Sie ihn in ein verfügbares Register und übergeben Sie dieses Register an Ihr Makro.

Um dies zu tun, können Sie ersetzen:

print ans, number 

mit:

mov eax, [rel number] ; Get the 32-bit number from number and store in eax 
         ; Using RIP relative addressing 
print ans, rax  ; Print the 32-bit word in the bottom half of RAX. 

Das erweitern würde:

push rbp 

mov rdi, ans  ; RDI = Address of ans 
mov rsi, rax  ; RSI = number to print in RAX 

xor rax, rax 

call _printf 

pop rbp 

Hinweis: Wir verwenden mov eax, [rel number] mit der rel Richtlinie um die voreingestellte absolute Adresse zu ändern Anpassung an die relative Adressierung des RIP. Wenn Sie mov eax, [number] verwenden und nicht rel angeben möchten, können Sie die Standardadressierung überschreiben und default rel oben in der Assemblydatei platzieren. Der Standardwert ist default abs.


Sie fragen sich vielleicht, warum ich vorgeschlagen:

mov eax, [rel number] ; Get the 32-bit number from number and store in eax 
         ; Using RIP relative addressing 
print ans, rax   ; Print the 32-bit word in the bottom half of RAX. 

Statt:

print ans, [rel number] 

Letztlich wäre das Makro versucht, dies zu tun:

mov rsi, [rel number] ; Get the 64-bit number from number and store in RDI 

Sie definiert number dies weg:

number resd 1 

Dies ist ein 32-Bit-Wert, nicht 64-Bit. mov rsi, [rel number] hätte versucht, 8 Bytes vom Speicherplatz number in RSI zu verschieben. Dies wird wahrscheinlich keine Probleme in Ihrem Beispielcode verursachen, aber es wird als schlechtes Formular angesehen. Ich betrachte es als einen Fehler trotz der Tatsache, dass es funktionieren könnte.

+0

Es funktionierte, aber ich musste 'DEFAULT REL' oben setzen, um den nasm Fehler zu lösen. – SpilledMango

+0

Ich habe einen Kommentar dazu am Ende meiner Antwort geschrieben, aber es hätte 'mov eax, [rel number]' ohne 'default rel' an der Spitze akzeptieren sollen. –