2016-04-24 14 views
1

このコードがなぜ機能しないのかわかりません。私はscanf関数をdoubleに、printfを同じdoubleに使う必要があります。 このコードを使用すると、結果が良好ではありません。私が見るものはかなりランダムな文字です。ASM x64 scanf printf double、GAS

.data 

d1: .double 


format: .asciz "%lf\n" 
format2: .asciz "%lf" 

.text 
.globl main 

main: 

subq $8, %rsp 

#scanf 
movq $0, %rax 
movq $d1, %rsi 
movq $format2, %rdi 
call scanf 
addq $16, %rsp 

#printf 
movq $1, %rax 
movsd d1, %xmm0 
movq $format, %rdi 
call printf  
addq $16, %rsp 

#exit 
movq $1, %rdi 
xorq %rax, %rax 
call exit 
+2

デバッガを、ステップスルー、レジスタの値を見ます。 –

+1

これはおそらく問題ではありません。 'main'が返ってくることはなく、あなたは決してスタックメモリを読みませんが、それぞれの' call'の後にあなたの 'add $ 16、%rsp'でスタックを破壊しています。 '%rsp'は呼び出し保存されたレジスタなので、前と同じ値になります。また、 '.data'ではなく、' d1'をbssに入れてください。実行ファイルに値を格納する必要がないからです。実際はそれが問題です。 –

+0

^^ lol、panto comment: 'ああ、そうじゃないよ' ....ああ、そうだよ ' –

答えて

1

これが問題である:なし引数付き.doubleは何に組み立てるため、

.data 
d1: .double  # declares zero doubles, since you used an empty list 
format: .asciz "%lf\n" 

d1formatは、同じアドレスを持っています。 (「.double expects zero or more flonums, separated by commas. It assembles floating point numbers.」)。

したがってscanfは、printfに使用するフォーマット文字列を上書きします。これはprintfが印刷するランダムなゴミです。

修正プログラムは、実際にはbssにある程度のスペースを確保することが望ましいです。 、効率的なアセンブラコードを書くことについてより多くのものについて

#.bss 
# .p2align 3 
# d1: .skip 8   ### This is the bugfix. The rest is just improvements 

# or just use .lcomm instead of switching to the .bss and back 
.lcomm d1, 8 

.section .rodata 
print_format: .asciz "%f\n"  # For printf, "%f" is the format for double. %lf still works to print a double, though. Only %llf or %Lf is long double. 
scan_format: .asciz "%lf"  # scanf does care about the trailing whitespace in the format string: it won't return until it sees something after the whitespeace :/ Otherwise we could use the same format string for both. 

.text 
.globl main 
main: 
    subq $8, %rsp 

    xor %eax,%eax 
    mov $d1, %esi   # addresses for code and static data are always in the low 2G in the default "small" code model, so we can save insn bytes by avoiding REX prefixes. 
    mov $scan_format, %edi 
    call scanf 

    mov $1, %eax 
    movsd d1, %xmm0 
    mov $print_format, %edi 
    call printf 

    add $8, %rsp 
    ret 

    #xor %edi,%edi # exit(0) means success, but we can just return from main instead. It's not a varargs function, so you don't need to zero rax 
    #call exit 

タグのwikiのリンクを参照してください(。それはいくつかの特定のgccのポートのことだにもかかわらずThis doc explains it well、)その代わり

、これを使用しています。


はまた働いていたが、あなたの実行可能では8バイト無駄だろう:

.data 
d1: .double 0.0 
+0

ありがとうございます!もちろん、このコードは私のために働いた。 – zderzak678