我試圖了解如何在 Linux 中的 x86-64 程式集中正確使用堆疊。我將一些數字推入堆疊,然后我想取堆疊中的頂部數字并列印適當的 ASCII 值。但它每次列印不同的東西。請幫助我理解為什么下面的代碼會這樣。
.section .bss
.comm x, 4
.section .text
.globl _start
_start:
push $52
push $65
mov %rsp, (x)
mov $1, %rax
mov $1, %rdi
mov $x, %rsi
mov $1, %rdx
syscall
mov $60, %rax
movb $0, %dil
syscall
另外,如果您能給我一些資源,讓我可以學習在匯編中使用堆疊,我將不勝感激。
uj5u.com熱心網友回復:
該指令mov %rsp, (x)將 RSP(當前堆疊指標)的值寫入x記憶體中的位置,該位置位于您的.bss部分中。然后,您正在做mov $x, %rsi:這將的地址x移動到 RSI 中,因此 RSI 將指向您的.bss變數,該變數保存堆疊指標的值。當您嘗試write從 RSI 指向的記憶體中發出系統呼叫讀取時,您的輸出將是您在那里保存的 RSP 的最低有效位元組。由于每次執行程式時堆疊的位置都會有所不同,這就是為什么每次都會得到不同輸出的原因。
此外,您在保留空間.bss用.comm x, 4,但你正在RSP到它mov %rsp, (x),這是一個8位元組的移入。
要將值從堆疊列印到標準輸出,您真正想要做的很簡單mov %rsp, %rsi。你根本不需要x:
.section .text
.globl _start
_start:
push $65
mov $1, %rax
mov $1, %rdi
mov %rsp, %rsi
mov $1, %rdx
syscall
mov $60, %rax
mov $0, %rdi
syscall
上面的代碼應該輸出A并退出。
如果要在 中使用中間變數.bss,則必須執行兩次移動以使用中間暫存暫存器將值從堆疊復制到其中(因為mov一次只能使用一個記憶體運算元):
.section .bss
.comm x, 4
.section .text
.globl _start
_start:
push $65
movb (%rsp), %al
movb %al, (x)
mov $1, %rax
mov $1, %rdi
mov $x, %rsi
mov $1, %rdx
syscall
mov $60, %rax
mov $0, %rdi
syscall
另外,請注意,在 Linux上,在 x86 上采用 4 個位元組exit的intas 引數,因此movb $0, %dil通常是不夠的。在您的情況下,沒關系,因為您之前將 RDI 設定為1并且 RDI 保留在syscall.
通常,您可以使用
xor
