0

現在、64ビットマシンでアセンブリNASMを作成して、特定の入力の階乗を出力し、入力を返しています。プログラムは階乗値を出力するために正しく動作しますが、戻り値は入力を返しません。はい、コードはひどいものです。単純にすべてを書き直してほしくないのです。(これは私の宿題です。)リターンレジスタ(rax)が最初から持っていた値を保持していない理由を誰かに説明してもらいたいだけです。

extern read_input
extern print_int
call read_input

push rax   ;save n
mov rcx, 1 ;counter
push rcx   ;save counter
push rdi   ;save print int

jmp test

print:
pop rdi
imul rdi, rcx ;multiply by current counter
push rdi      ;save our multiplication factor
call print_int

pop rdi
pop rcx 
pop rax    ;restore trashed variables
add rcx, 1 ;increment counter by 1
push rax   ;push stuff back on stack
push rcx
push rdi

jmp test

test:
cmp rcx, rax
jle print

pop rax 
pop rcx 
pop rdi ;clear stack
ret

出力:

Please enter an input value:
read_input> Returning 4 (0x4)
Printing integer 1 (0x1)
Printing integer 2 (0x2)
Printing integer 6 (0x6)
Printing integer 24 (0x18)
Program complete.  Return 24 (0x18)

入力を返すようにしたいのですが、この場合は 4 になります。

任意の洞察をいただければ幸いです。

4

2 に答える 2

2

プッシュとポップの順序が間違っています。

プッシュ:

push rax   ;save n
mov rcx, 1 ;counter
push rcx   ;save counter
push rdi   ;save print int
...
push rax   ;push stuff back on stack
push rcx
push rdi

ポップス:

pop rdi
pop rcx 
pop rax    ;restore trashed variables
...
pop rax 
pop rcx 
pop rdi ;clear stack
ret

最後にraxrdiが入れ替わります。

于 2012-09-29T02:05:20.927 に答える
1

問題は、スタック内の場所には名前や識別子がないということです。同じ順序でプッシュしてポップする必要があります。と言うpop raxと、プロセッサは「によって作成された最後のエントリはどこpush raxですか?」と言うのではなく、「最後にプッシュされるものはどこですか?」と言います。したがって、スタックは次のようになります (rax 1、rbx 2、rcx 3 を想定):

0x0001 #push rax
0x0002 #push rbx
0x0003 #push rcx
  |
  \----- This is the value retrieved by pop rax

このルールに従ってください: 明示的に値を切り替えようとしている場合を除き (これは で行う方が適切です)、常にポップするのと同じ順序でプッシュしますxchg

注: 間違った順序で実行すると、rflagsレジスタなどの値を設定するために使用できます。

push 0x0000000000000000 ;New value for rflags
popf ;Pop it into rflags
于 2012-09-29T02:11:40.743 に答える