0

I try to use the SIB to specify an index in array, but it fails.

Here is the ko instruction :

0x48 (REX.W)
0x8B (MOV)
0x44 (ModRM with reg = RAX, SIB and disp8)
0x86 (base is RSI, scaled index is [RAX*4]
XXXX (the disp8)

With that the computed address should be [RSI + 4*RAX + disp8], right ?

The same code works when I replace the SIB by 0x26 (ie base=RSI, no scaled index).

I don't get what's wrong.

Simon
  • 2,067
  • 2
  • 17
  • 30
  • I get a Segmentation fault – Simon Apr 25 '16 at 17:55
  • RAX is probably too big then, so the effective address ends up being outside the array – harold Apr 25 '16 at 18:13
  • 1
    Did you check with a disassembler that it's the right instruction? It's not in a very convenient format to paste onto a `db` or `.byte` directive. – Peter Cordes Apr 25 '16 at 18:40
  • @harold I did check EAX, and it was fine, and now I checked RAX, and yes that was the problem ... The fact is, I used a byte operation (SUB with disp8) and that was causing the issue. When I updated the SUB to a SUB disp32 it works. Do you know why ? – Simon Apr 25 '16 at 18:45
  • @PeterCordes I don't use an assembler. – Simon Apr 25 '16 at 18:48
  • 1
    @Simon: I know you're not talking about using an assembler. I said to check your binary with a **dis**assembler. – Peter Cordes Apr 25 '16 at 18:50
  • 1
    @Simon: Do you mean `sub r8, imm8`? 8 and 16bit operations don't zero the upper part of the register, but 32bit operations do. http://stackoverflow.com/questions/11177137/why-do-most-x64-instructions-zero-the-upper-part-of-a-32-bit-register. You would have been fine with a `sub r32, imm8`. – Peter Cordes Apr 25 '16 at 18:51
  • @PeterCordes Oh sorry I didn't knew about disassemblers. I will have a look. – Simon Apr 25 '16 at 18:51
  • voted to close as no longer reproducible (problem was outside of what the question's asking about). – Peter Cordes Apr 25 '16 at 18:53
  • @PeterCordes yes I meant imm8 & imm32. I used SUB AL, imm8. – Simon Apr 25 '16 at 18:59
  • 1
    Yup, I figured. Note that the encoding for `sub r32, imm8` is shorter than the eax-only encoding for `sub eax, imm32`, so you should use `sub eax, imm8`. BTW, if you haven't heard of disassemblers, there's probably a lot of other stuff you haven't read. See the links in the [x86 tag wiki](http://stackoverflow.com/tags/x86/info), esp. Agner Fog's guide. – Peter Cordes Apr 25 '16 at 19:03
  • @PeterCordes I was trying to use the opcode that hardcodes the AL register in it, because it is only one byte (2C). SUB r/m64, imm8 uses 2 more bytes : REXW and the modrm. But when I use 2C, the next MOV that uses RAX *as a value* (not even an address) fails with a seg fault. That means single byte operand opcodes make the upper part of the register garbage/unaccessible ? – Simon Apr 25 '16 at 19:21
  • @PeterCordes thanks for the info & links BTW – Simon Apr 25 '16 at 19:23
  • 1
    I understood what you were trying to do. Writing `al` has no effect on the `ah`, or the rest of `rax`. If it had garbage before, it will still have garbage. If the top 32b of `rax` is garbage, but all of `eax` has what you want, then you should use `sub eax, imm8` to zero-extend 32 to 64bit for free. If there's garbage in the bottom 32, you need `movzx eax, al` to zero-extend to the whole 64bit register. – Peter Cordes Apr 25 '16 at 19:26
  • I continued investigating because your remark didn't seemed to match my tests, and I realized I was writing RAX over my code ... Thus the seg fault, and no seg fault when I used bigger instructions that let more place for the overwrite... I corrected that and now the SUB AL imm8 does work as intended. Thanks a ton for the help ! – Simon Apr 25 '16 at 19:59

0 Answers0