E. Shcherbo
E. Shcherbo

Reputation: 1148

Two's complement representation of numbers

The question is about the Practice Problem 2.18 from the Computer Systems: A Programmer Perspective by Randal Bryant which states:

For the lines labeled A–I (on the right) in the following listing, convert the hexadecimal values (in 32-bit two’s-complement form) shown to the right of the instruction names (sub, mov, and add) into their decimal equivalents (this is a disassembled program):

4004d0: 48 81 ec e0 02 00 00 sub $0x2e0,%rsp A 736
4004d7: 48 8b 44 24 a8 mov -0x58(%rsp),%rax B -88
... ... ...

If I understand correctly from the problem "shown to the right of the instruction names" means these values - 0x2e0 and -0x58. But they don't seem to be in the two's complement form, they are just unsigned integers with the minus sign before them (probably I'm missing something).

What do I understand wrong here? Where are 32-bit hex values written in the two's complement form?

Upvotes: 0

Views: 615

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 363902

That's a weird question, yeah. They're in little-endian 2's complement in the hexdump of the machine code, but showing you sign/magnitude human-readable hex in the disassembly kind of gives the game away: yes you just do hex->decimal conversion of the magnitude part, and keep the sign.

e.g. in the SUB instruction encoding:

48         81      ec     e0 02 00 00      sub  $0x2e0,%rsp

REX.W=1  opcode  modrm    imm32 (little-endian)

Or in the mov:

48       8b     44     24     a8                         mov  -0x58(%rsp),%rax
REX.W=1 opcode  ModRM  SIB   disp8 (signed 8-bit 2's complement)

The a8 displacement sign-extends to 64-bit address-size as 0xffffffffffffffA8; in CPU hardware the addressing mode is that plus RSP.

Or more easily to get a human-readable sign/magnitude representation, just do 0xa8 - 0x100 = -0x58 to range-shift / decode this 8-bit 2's complement bit-pattern that has its sign-bit set.

(Or of course take the 2's complement inverse to get the magnitude and remember that it was negative, e.g. 0x00 - 0xa8 with wrapping to 8-bit, or use the -x = ~x+1 identity that for some reason many people prefer over one simple subtraction from zero.)

Upvotes: 4

Related Questions