2017-04-18 16 views
1

1つの番号をとり、それを印刷したアセンブリプログラムを作成しようとしました。しかし、私が1を書いたとき、それは4171を書きました。なぜ、どうすればいいですか?私は、64ビットアセンブリを使用しています、私はnasm -f macho64 scanf.asmとそれを組み立て、gcc -o scanf scanf.o -Wl,-no-pieでリンクしました。そして、私はスキャンマクロ(varible番号へのポインタのために)の周りに角括弧を使用しようとしましたが、マスマッハーは許可しませんでしたので、私はそれをしませんでした。アセンブリ番号変更エラー

; 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

あなたの 'print ans、number'は、数値そのものではなく、' number'のアドレスを表示しているようです。 'print ans、number'を' movsx rax、dword [number] '' 'print ans、rax'に置き換えるとどうなりますか?この場合、 'mov eax、[number]' 'print ans、rax'もうまくいくはずです。 –

+0

"movs rax、dword [number]"を試してみると、 "movf razを試してみると、scanf.asm:12:エラー:Mach-O 64ビットフォーマットが32ビット絶対アドレスをサポートしていません"数]"。 – SpilledMango

+0

これで 'mov rax、[rel number]'が相対RIPアドレッシングを使用するようにしてください。 –

答えて

2

マクロは答えが間違って印刷する:

は、ここに私のコードです。マクロが展開されている場合

print ans, number 

あなたが取得したい:

push rbp 

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

xor rax, rax 

call _printf 

pop rbp 

を私が2本の以上のラインとその意味をコメントしています。フォーマット文字列'You wrote: %d'は、整数を出力します。代わりにnumberのアドレスを渡しました。これを解決するには、numberから32ビットの値を取得し、使用可能なレジスタに置き、そのレジスタをマクロに渡します。これを行うには

あなたは置き換えることができます。

print ans, number 

で:

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 

:に拡大する

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. 

我々は relディレクティブで mov eax, [rel number]を使用しますデフォルトの絶対アドレスを変更するRIP相対アドレス指定よりも劣っています。 mov eax, [number]を使用し、 relを指定する必要がない場合は、デフォルトのアドレッシングをオーバーライドして、 default relをアセンブリファイルの先頭に配置できます。デフォルトは default absです。


私は提案理由をあなたは尋ねることがあります。

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. 

むしろより:

print ans, [rel number] 

最終的にマクロがこれを行うにしようとしているだろう:

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

あなたが定義されnumber way:

number resd 1 

これは64ビットではなく、32ビットの値です。 mov rsi, [rel number]は、メモリロケーションnumberから8バイトをRSIに移動しようとしました。これにより、サンプルコードで問題は発生しない可能性がありますが、悪い形とみなされます。私はそれがうまくいくかもしれないという事実にもかかわらず、バグだと思う。

+0

それはうまくいったけど、nasmのエラーを解決するために、最初に「DEFAULT REL」を入れなければならなかった。 – SpilledMango

+0

私は答えの一番下にコメントをつけましたが、一番上に 'default rel'を付けずに' mov eax、[rel number] 'を受け入れるべきでした。 –