-1

I am trying to understand the following behavior:

mov bl, 51 ; now print $ebx in gdb returns 51         
mov bh, 52 ; now it is 13363 but I thought it would be 5251

Why? I use Linux nasm on Intel x86

Cœur
  • 37,241
  • 25
  • 195
  • 267
danielleontiev
  • 869
  • 6
  • 26
  • 3
    You used decimal, not hex. So `52*256+51=13363` – Jester Dec 17 '17 at 23:19
  • why did you expect 5251? – Ped7g Dec 17 '17 at 23:24
  • @Ped7g I expect this cause of this picture https://imgur.com/a/LmGLb – danielleontiev Dec 17 '17 at 23:27
  • 3
    @danielleontiev that's sort of correct way of thinking, but you missed the important basic fact, that both `bh` and `bl` are "8 bits" registers. When you write in assembler `mov bl,51`, the assembler will emit binary machine code, converting the value `51` for you into binary 8 bit value `0011_0011` (which is `51` when interpreted as decimal integer). So you load `bl` with `0011_0011` and `bh` with `0011_0100` (`0x34` or `52`), then `bx` is equal to `0011_0100_0011_0011` = 16 concatenated bits. But your `print $bx` will interpret those 16 bits as decimal value, which is equal to `13363`. – Ped7g Dec 17 '17 at 23:32
  • @Ped7g thanks a lot, now it's clear. I think your comment can be the answer – danielleontiev Dec 17 '17 at 23:38
  • 1
    @danielleontiev for me the Peter's answer is saying basically the same thing, also he adds the note you are printing `ebx` when you did not set upper 16 bits of it, so that can be source of another unexpected values. But for me the conversion between hex and binary is very easy, as I fully understand that each hexadecimal digit is exactly 4 bits, so I write bit values usually in hexa, converting them in head. Yet for a beginner like you it may be the final missing piece of puzzle, to realize that there's direct physical connection to the "bit" inside CPU (cell with voltage) and values encoding – Ped7g Dec 17 '17 at 23:53

1 Answers1

1

When you print a 16-bit integer, you don't separately convert the two bytes to decimal strings and concatenate them. You have to convert the entire 16-bit number to a string of place-value digits.

The reason it doesn't work is that base 10 is not a power of 2. For bases that evenly divide 256, like hex, doing each byte (or 4-bit nibble for hex) separately does work.

e.g. bh=0x34 : bl=0x33 gives you 52*256 + 51 = 0x3433

This is one reason that converting to hex is so much easier (as well as more efficient) than converting to decimal: you can start with the most-significant digit first.

For bases that aren't congruent to 256 (if that's the right terminology), dividing by the radix (e.g. dividing by 10 to get the low digit) changes the upper bits


BTW, note that writing to BL and BH doesn't zero the upper 2 bytes of EBX. The 16-bit concatenation of BH:BL is addressable as BX, not EBX. But if the upper 2 bytes of EBX are zero, then printing EBX is the same as BX.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847