问题
Here is what i want to do:
add rsi, word [rsi+16]
I want to read the unsigned short value which is at rsi+16 adress. And i want to add this value to rsi.
Here is the error i get in nasm:
s2.asm:62: error: mismatch in operand sizes
This is strange. Why nasm and my cpu are not able to add 16 bits to 64 bits register ?
Here is what i do which works:
mov rbx,0
mov bx, word [rsi+16]
add rsi, rbx
This is strange is there a best way to do that ?
Thanks
回答1:
Instruction operands must have the same size, except sign and zero extend move instructions.
In your case, you can add 16 bits to 64 bits register rsi
in one instruction only this way:
add si, word [rsi+16]
translated into:
\x66\x03\x76\x10
Because si
register(size a word) is a low part of rsi
register, you can add to si
without disturbing the upper bytes of rsi
.
But it will work the same as a 64-bit add only if the 16-bit add result doesn't overflow. For example:
Let's say we have esi=0x0000FFFF
, and we add 1 to si
. We've got esi=0x00000000
. And CF will be set, because of carry-out from the 16-bit add.
If you do need carry to propagate to the rest of RSI, zero-extend into any other register.
movzx rax, word ptr [rsi+16]
add rsi, rax
translated into:
\x48\x0F\xB7\x46\x10
\x48\x01\xC6
Also Ped7g noted:
but you will still pay performance penalty on some architectures, when you will use full
rsi
which is partially updated bysi
only, so performance wise it is still better to use some spare register to extend the word value to 64b first, and then add two 64b registers (if you will usersi
).
See also Why doesn't GCC use partial registers? for possible performance issues from writing SI and then reading RSI on P6-family CPUs, although that's not relevant for shellcode exploit payloads.
来源:https://stackoverflow.com/questions/49152958/add-16-bits-to-64-bits-register