理論問題。但是假設我寫了一個匯編程式。我有“labelx:”我希望程式讀取這個記憶體地址并且只有這個大小并列印到標準輸出。
會不會是這樣的
jmp labelx
然后我會使用 Write syscall ,確保從 labelx 的下一條指令中讀取:
mov rsi,rip
mov rdi,0x01
mov rdx,?
mov rax,0x01
syscall
然后輸出到標準輸出。
但是,我將如何獲得讀取自身的大小?特別是如果在我想閱讀的代碼或之后的代碼后面有一個標簽。我必須手動計算行數嗎?
mov rdx,rip (bytes*lines)
然后使用填充暫存器進行系統呼叫,以便系統呼叫從 rsi 寫入到 rdi。成為標準輸出。
這甚至可能嗎?我是否必須首先使用讀取系統呼叫,因為寫入系統呼叫需要為 rsi 分配記憶體緩沖區。但是我假設 .text 已經分配了記憶體并且是只讀的。我是否必須在寫入之前先分配到堆疊或堆或靜態緩沖區,如果它甚至可能放在首位?
順便說一句,我正在使用 NASM 語法。而且組裝很新。只是一個問題。
uj5u.com熱心網友回復:
是的,該.text部分只是記憶體中的位元組,與.rodata您通常放置的部分沒有什么不同msg: db "hello", 10。x86 是馮諾依曼架構(不是哈佛),因此代碼指標和資料指標之間沒有區別,除了您選擇使用它們做什么。在鏈接的可執行檔案上使用objdump -drwC -Mintel以查看機器代碼位元組,或x在正在運行的行程中使用 GDB 的命令,以查看任何位置的位元組。
您可以通過將標簽放在所需部分的開始/結束處,并mov edx, prog_end - prog_start在代碼中使用 RDX 中您想要該大小的點,讓匯編器計算大小。
請參閱$ 如何在 NASM 中作業,究竟是什么?有關減去兩個標簽(在同一部分中)以獲得大小的更多資訊。$(當前行開頭的隱式標簽在哪里,盡管$這不太可能是您想要的。)
要將當前地址存入暫存器,您需要一個相對于 RIP 的 LEA,而不是mov,因為 RIP 不是通用暫存器,并且沒有mov讀取它的特殊形式。
here:
lea rsi, [rel here] ; with DEFAULT REL you could just use [here]
mov edi, 1 ; stdout fileno
mov edx, .end - here ; assemble-time constant size calculation
mov eax, 1 ; __NR_write
syscall
.end:
與您使用mov esi, here. (如何將函式或標簽的地址加載到暫存器中)
LEA可以用來lea rsi, [rel $]組裝成相同的機器代碼位元組,但你需要一個標簽,這樣你就可以減去它們。
我優化了您的 MOV 指令以使用 32 位運算元大小,隱式零擴展為完整的 64 位 RDX 和 RAX。(還有 RDI,但write(int fd, void *buf, size_t len)無論如何只查看檔案描述符的 EDI)。
請注意,您可以write使用任何部分的任何位元組;讓一段代碼自己撰寫并沒有什么特別之處。 在上面的示例中,將開始/結束標簽放在任何地方。(例如foo:and .end:,并mov edx, foo.end - foo利用 NASM 本地標簽的作業原理,通過附加到先前的非本地標簽,因此您可以從其他地方參考它們。或者只是給它們兩個非點名稱。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/424421.html
上一篇:為什么編譯器將RDI復制到另一個暫存器,然后在回圈內將其復制回RDI?
下一篇:x86除法例外-回傳地址
