[英]Can't understand assembly mov instruction between register and a variable
我在Linux 64位上使用NASM匯編程序。 我無法理解某些帶有變量和寄存器的東西。 我創建一個名為“ msg”的變量:
msg db "hello, world"
現在,當我要寫入標准輸出時,將msg
移至rsi
寄存器,但是我不按位理解mov
指令... rsi寄存器由64位組成,而msg變量具有12個符號,每個符號8位,這意味着msg變量的大小為12 * 8
位,明顯大於64位。
因此,如何制作這樣的指令呢?
mov rsi, msg
,而不會溢出分配給rsi的內存。
還是rsi寄存器包含字符串的第一個符號的存儲位置,並且在寫入1個符號后將其更改為下一個符號的存儲位置?
抱歉,如果我寫的是完全廢話,我是組裝的新手,一會兒我就無法掌握它。
在NASM語法(與MASM語法不同)中, mov rsi, symbol
將mov rsi, symbol
的地址放入RSI。
mov rsi, [symbol]
將加載從symbol
開始的8個字節。 編寫這樣的指令時,您可以選擇一個有用的位置來加載8個字節。
mov rsi, msg ; rsi = address of msg
movzx eax, byte [rsi+1] ; rax = 'e' (upper 7 bytes zeroed)
mov edx, [msg+6] ; rdx = ' wor' (upper 4 bytes zeroed)
請注意,可以使用mov esi, msg
因為符號地址始終適合32位(在默認的“小”代碼模型中,所有靜態代碼/數據都位於2GB的虛擬地址空間中)。 NASM使用匯編時間常量(例如mov rax, 1
)為您進行了優化,但可能無法使用鏈接時間常量。 為什么大多數x64指令將32位寄存器的高位歸零
在寫入1個符號后,它會更改為下一個符號的存儲位置嗎?
不,如果您需要,必須增加inc rsi
。 沒有魔術。 指針就是您可以像其他整數一樣操作的整數,而字符串只是內存中的字節。
訪問寄存器不會神奇地修改它們。
有諸如lodsb
和pop
類的指令從內存加載並遞增指針(分別為rsi
或rsp
),但是x86沒有任何前/后遞增/遞減尋址模式,因此即使使用mov
也無法獲得該行為如果你想要的話。 使用add
/ sub
或inc
/ dec
。
免責聲明:我不熟悉您要處理的程序集的樣式,因此以下內容更為籠統。 特定的口味可能比我以前習慣的功能更多。 通常,程序集處理大小取決於處理器的單字節/字實體。 我已經在8位和16位處理器上做了大量工作,所以這就是我的答案所在。
關於匯編的一般說明:匯編就像是一種高級語言,只是您必須處理更多細節。 因此,如果您習慣使用C語言進行某些操作,則可以從那里開始,然后進一步細分該操作。
例如,如果您聲明了兩個要添加的變量,那么在C語言中這很簡單:
x = a + b;
在組裝中,您必須進一步分解:
mov R1, a * get value from a into register R1
mov R2, b * get value from b into register R2
add R1,R2 * perform the addition (typically goes into a particular location I'll call it the accumulator
mov x, acc * store the result of the addition from the accumulator into x
根據組裝和處理器的風格,您也許可以直接在加法指令中引用變量,但是就像我說的那樣,我必須查看所使用的特定風格。
對您的特定問題的評論:如果您有一串字符,則必須使用某種循環分別移動每個字符。 我將設置一個寄存器來包含您字符串的起始地址,然后在每個字符移動后遞增該寄存器。 它的作用類似於C中的指針。您將需要某種指示字符串的終止或其他值來指示字符串的大小,以便知道何時停止。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.