我正在看一個由 NASM 組裝的英特爾組件的示例。它有以下指令:
add byte [ebx], 32
我如何從檔案中知道“位元組”的作用?
我正在閱讀的書在文本中解釋了“位元組”如何告訴匯編程式我們只將單個位元組寫入ebx. 我不清楚通過查看檔案我是如何知道這一點的。
ADD從書中和其他地方的示例來看,該指令看起來有兩種形式:
ADD <dest> <src>ADD <size> <dest> <src>
但是,當我查看英特爾檔案 [1] 時,我看不到任何與我的任何一種形式相似的東西。表中給出的每條指令都只有一個逗號,在我看來,這使得所有相應的操作碼似乎只需要兩個輸入。有一個表格給出了“指令運算元編碼”。運算元 3 和 4 不適用。環顧網路,大多數網站都沒有提及尺寸引數(更不用說它適用于我的處理器)。
我正在以 386 模式在 Intel(R) Core(TM) i7-6700HQ CPU 上組裝:
nasm -f elf -g -F stabs -o $OBJECTFILE $1
ld -m elf_i386 -o $BUILDNAME $OBJECTFILE
也許該指令需要一個額外的運算元 386 但不是較新的架構?
[1]“英特爾? 64 和 IA-32 架構軟體開發人員手冊組合卷:1、2A、2B、2C、2D、3A、3B、3C、3D 和 4”,卷。2A 3-31 pdf 中的第 605 頁。
https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
uj5u.com熱心網友回復:
asm 源中的byte關鍵字設定指令的運算元大小屬性。在機器代碼中,數字操作碼或 16/32/64 位運算元大小、當前 CPU 模式和非位元組操作碼的前綴暗示了這一點。 英特爾的手冊記錄了機器代碼形式,而不是 asm 源語法。
請參閱以下內容:如何將其編碼為機器代碼。
- x86-64 (AMD64) 架構中是否有默認運算元大小?
- x86 在執行指令和讀/寫資料時如何處理位元組尋址和字尋址?
- 當我們只知道操作碼的十六進制時如何編碼指令
這就是為什么匯編器也有與 ISA 手冊分開的手冊的原因。
例如,NASM 的手冊第 3 章:NASM 語言
3.1 NASM 源代碼行的布局描述了助記符和運算元的語法布局。不幸的是,該部分沒有提及您可以放在運算元前面的覆寫,只有像o16您可以放在助記符前面的前綴!(作為一種笨拙的手動方式來指定運算元大小。)
該手冊確實有在多個地方使用運算元大小覆寫的示例,例如在2.2 MASM 用戶快速入門中,它指出 NASM 需要,mov word [var], 2即使 varvar dw 0在 MASM 中會神奇地暗示該指令的運算元大小。并在用于強制立即編碼時strict提到相同的說明符,而不僅僅是運算元大小。例如add ecx, strict dword 123強制add r/m32, imm32形式,同時add ecx, dword 123仍然允許add r/m32, imm8形式。(https://www.felixcloutier.com/x86/add)
其他一些 x86 匯編程式,如 GAS 和 clang/LLVM,默認使用AT &T 語法,這與英特爾手冊用于討論指令的語法大不相同,其中運算元大小由指令助記符上的后綴指定(如果需要),例如movb $'a', (%rdi)MASM mov byte ptr [rdi], 'a'(注意額外的ptr關鍵字)或 NASMmov byte [rdi], 'a'
匯編語法取決于工具,而不是 ISA。英特爾的手冊,尤其是第 2 卷,列出了每條可用指令的部分,并沒有詳細說明如何在 asm 源中指定運算元大小的語法細節,因為它會模棱兩可。
在 asm 源代碼中,暫存器可以暗示運算元大小
對于兩個運算元必須相同大小的指令,暫存器運算元暗示 asm 源語法中的運算元大小,因此您無需指定它。例如add eax, [rdi]不需要add eax, dword [rdi]。
但是 mov-immediate to memory(或任何其他op mem,imm指令)是模棱兩可的,單運算元記憶體指令(inc [mem]如shl [rdi], cl/q) 或movzx eax, [rdi](源大小可以是位元組或字)
請參閱何時需要在 Assembly 中指定運算元的大小?
像 NASM 這樣的優秀匯編程式會在這種歧義上出錯。不太好的匯編器有時只會選擇一個默認值。例如,GAS 選擇 dword 來獲取除 MOV 之外的指令,例如add $1, (%rdi),并且直到最近才添加了一個警告!
同樣,[rdi rax]指定 64 位地址大小,而[edi eax]指定 32 位地址大小。類似的默認地址大小(在 asm 源中)[1234]是當前模式的位數,即不使用67機器代碼中的地址大小前綴。
同樣,這 100% 是關于 asm 源代碼級別的語法。將指令編碼為特定模式的機器代碼必然意味著運算元大小。
這就是為什么您需要告訴匯編程式 CPU 將以何種模式解碼。例如,bits 32如果您在引導加載程式中制作平面二進制檔案或切換模式,則使用 NASM。或者更常見的是通過組裝nasm -felf64來制作一個 64 位目標檔案。在這種情況下,bits 32會讓您將不匹配的機器代碼放入錯誤的目標檔案中,而不是在匯編時因push ebx無法編碼為 64 位模式而導致錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/459720.html
