簡體   English   中英

編譯匯編程序操作碼

[英]Compiling Assembler Opcodes

我想知道是否有可能用等效的操作碼代替匯編程序指令。 (即能夠編譯操作碼而不是指令)如果可以,是否可以在運行時操作這些操作碼? 干杯

如果有可能用等效的操作碼替換匯編程序指令。

是的,您可以編譯操作碼,生成的機器代碼將相同。

例如x86-32簡短的無用匯​​編代碼:

uselessFunc:
    xor  eax,eax
    ret

也可以用操作碼編寫:

uselessFunc:
    db  0x31, 0xC0    ; opcode "xor eax,eax"
    db  0xC3          ; opcode "ret"

這兩個源都將產生相同的三個字節的機器代碼: 31 C0 C3

是否可以在運行時操作這些操作碼

這與來源的形式完全無關。 在運行時,您可以操作任何具有寫訪問權限(理想情況下為讀+寫訪問)的內存。 但是,在修改操作碼后,如果要運行它們,則還需要執行對該內存的訪問。

在具有現代操作系統(如linux)的現代x86機器上,這不是默認配置,默認情況下,代碼段為只讀+可執行文件,而數據段為讀寫+可執行文件,但不是可執行文件,因此,如果您嘗試修改代碼的操作碼,則會在寫入期間因無效的內存訪問而崩潰,如果嘗試在數據段中執行操作碼,則會觸發no-exec錯誤。

因此,像Java VM等類似的應用程序會在運行時生成代碼,然后執行(“ JIT”即時編譯器在運行時將.class文件中的Java操作碼編譯為本地機器代碼,以提高零件的性能)重復執行的代碼)不僅會產生/修改操作碼,而且還會通過其他系統調用來管理目標存儲器頁面,以使其首先可寫入,然后將其更改為“未讀+執行”代碼存儲器頁面。 即通常是可能的,但是在許多目標環境中,您必須使用其他系統服務才能使其正常工作。

請記住,在現代時代,自我修改代碼被認為是不好的做法,不僅因為它更難調試,而且如果以幼稚的方式使用,它可能會帶來巨大的性能影響(例如,在x86 CPU上修改操作碼的例子很少執行之前的字節將使CPU中所有可能的高速緩存/預取行無效,從而使其在重新讀取/解碼指令時停頓一會兒。 而且在某些CPU上,內存/緩存模型比x86弱,因此過晚修改操作碼可能會被CPU忽略,因為它已經解碼了舊內容並將執行該內容。

但是只要您知道自己在做什么,就可以生成/修改操作碼。 它只是完全不依賴於源代碼的形式,無論如何生成原始二進制文件,無論是使用匯編語言還是C語言源代碼編寫這些操作碼,還是直接在hexa編輯器中將它們編寫為字節值都無所謂。

通過上面的兩個示例,在兩種情況下都可以執行以下操作:

mov   byte [uselessFunc+1],0xD8 ; modify xor eax,eax to xor eax,ebx

如果您將獲得對目標內存區域的寫訪問權,並且將保留可執行權限,則在兩種情況下,這會將xor eax,eax轉換為xor eax,ebx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM