これが問題である:なし引数付き.double
は何に組み立てるため、
.data
d1: .double # declares zero doubles, since you used an empty list
format: .asciz "%lf\n"
d1
とformat
は、同じアドレスを持っています。 (「.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
をx86タグのwikiのリンクを参照してください(。それはいくつかの特定のgccのポートのことだにもかかわらずThis doc explains it well、)その代わり
、これを使用しています。
はまた働いていたが、あなたの実行可能では8バイト無駄だろう:
.data
d1: .double 0.0
デバッガを、ステップスルー、レジスタの値を見ます。 –
これはおそらく問題ではありません。 'main'が返ってくることはなく、あなたは決してスタックメモリを読みませんが、それぞれの' call'の後にあなたの 'add $ 16、%rsp'でスタックを破壊しています。 '%rsp'は呼び出し保存されたレジスタなので、前と同じ値になります。また、 '.data'ではなく、' d1'をbssに入れてください。実行ファイルに値を格納する必要がないからです。実際はそれが問題です。 –
^^ lol、panto comment: 'ああ、そうじゃないよ' ....ああ、そうだよ ' –