NASM - The Netwide Assembler

NASM Forum => Programming with NASM => Topic started by: Amumu on November 30, 2016, 07:39:55 AM

Title: NASM generates wrong SIB byte?
Post by: Amumu on November 30, 2016, 07:39:55 AM
I am experimenting with SIB byte, by writing this simple instruction, save it in a file and compile as flat binary format:

Code: [Select]
jmp [ecx*2]
But then, the generated code is (from the output of hexdump):

Code: [Select]
00000000  67 ff 24 09                                       |g.$.|
0x67 is the address-override prefix.
0xff is the opcode for jmp instruction.
0x24 is the ModR/M byte that indicates an SIB byte follows.
finally, the SIB byte value 0x09 is equivalent to [ECX] addressing mode, while my code is
Code: [Select]
[ecx*2], according to table 2-3 in Intel's manual volume 2, instruction reference.

For ecx*4 and ecx*8, it works correctly. For example:

Code: [Select]
jmp [ecx*4]
The generated code is:

Code: [Select]
00000000  67 ff 24 8d                                       |g.$.|
0x8d is equivalent to [ECX*4].


Title: Re: NASM generates wrong SIB byte?
Post by: Frank Kotler on November 30, 2016, 09:45:23 AM
Interesting... Nasm seems to interpret [ecx * 2] as [ecx + ecx]. [nosplit ecx * 2] may do what you want (if you care - the first version is shorter).

Best,
Frank

Title: Re: NASM generates wrong SIB byte?
Post by: stressful on November 30, 2016, 01:24:08 PM
I don't think it's wrong. Your SIB byte is

Code: [Select]
Scale  Index  Base
00      001     001  = 9 (all are in place: scale = 0, Index = ECX, Base = ECX)

Your R/M flags is 100b, means you have a SIB byte without any displacement.

Code: [Select]
MOD byte
MD  = 00b
Reg = 100b
R/M = 100b  = 24

So from ISA from point of view, this is correct. Maybe you are implying something different in your code that leads to the confusion.
Title: Re: NASM generates wrong SIB byte?
Post by: Amumu on November 30, 2016, 02:33:11 PM
I don't think it's wrong. Your SIB byte is

Code: [Select]
Scale  Index  Base
00      001     001  = 9 (all are in place: scale = 0, Index = ECX, Base = ECX)

Your R/M flags is 100b, means you have a SIB byte without any displacement.

Code: [Select]
MOD byte
MD  = 00b
Reg = 100b
R/M = 100b  = 24

So from ISA from point of view, this is correct. Maybe you are implying something different in your code that leads to the confusion.
Yes, it was a confusion, because there's a SIB byte for [ecx*2]. I expect it to be 49h, not 09h. But then, thanks to Frank's answer, I read the manual, now I know that to save some space (no offset field). For that reason, 09h (which is [ecx + ecx]) is used instead of 49h (which is [ecx*2]).
Title: Re: NASM generates wrong SIB byte?
Post by: stressful on November 30, 2016, 03:31:50 PM
Amumu, it has nothing to do with compiler optimization or space saving feature of NASM. It is what it is.

[ecx+ecx] emits exactly the same encoding as [ecx*2] =>  66 FF 24 09

SIB byte 0x49 on the other hand translates to [ecx+ecx*2] => 66 FF 24 49

You may get the correct answer, but perhaps you still get the wrong idea about it.


Title: Re: NASM generates wrong SIB byte?
Post by: Amumu on November 30, 2016, 03:37:40 PM
Amumu, it has nothing to do with compiler optimization or space saving feature of NASM. It is what it is.

[ecx+ecx] emits exactly the same encoding as [ecx*2] => 66 FF 24 09

SIB byte 0x49 on the other hand translates to [ecx+ecx*2] => 66 FF 24 49

You may get the correct answer, but perhaps you still get the wrong idea about it.
I see. I thought that the base can be omitted, and when doing so, it ignores the base, e.g. [ecx*2] means no base, and uses only the scale index instead. Apparently, this is not the case, and in order to get an SIB byte generated, base must be supplied. Otherwise, ModR/M suffices.

Thanks.