Author Topic: NASM generates wrong SIB byte?  (Read 7109 times)

Offline Amumu

  • Jr. Member
  • *
  • Posts: 5
NASM generates wrong SIB byte?
« 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].


« Last Edit: November 30, 2016, 10:32:54 AM by Amumu »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: NASM generates wrong SIB byte?
« Reply #1 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


Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: NASM generates wrong SIB byte?
« Reply #2 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.

Offline Amumu

  • Jr. Member
  • *
  • Posts: 5
Re: NASM generates wrong SIB byte?
« Reply #3 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]).

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: NASM generates wrong SIB byte?
« Reply #4 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.



Offline Amumu

  • Jr. Member
  • *
  • Posts: 5
Re: NASM generates wrong SIB byte?
« Reply #5 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.