1

I believe this piece of code works, but it really seems like it shouldn't, unless ax is being compared with 0000 1010 instead of 1010 0000. Isn't it not supposed to matter whether data is stored in little or big endian format?

Here's the relevant bit of code:

mov    al, es:100h
mov    ah, 0
and    ax, 0A0h
cmp    ax, 20h
...

Isn't the value is ax something like this:

mov    al, es:100h  ; ax = ???? ????
mov    ah, 0        ; ax = 0000 ????
and    ax, 0A0h     ; ax = 0000 0000 or ax = 0000 ?0?0
cmp    ax, 20h      ; only useful if ax = 0000 ?0?0
...

Clearly there's a rule that I don't know here. An explanation would be super helpful.

EDIT: I should mention that I have looked for an answer but could not find one. For instance, this thread only made it seem more like the code must be wrong. But I'm pretty confident it works: Bitwise operators and "endianness"

Community
  • 1
  • 1

3 Answers3

2

I don't think there is a problem here. Your first instruction is:

mov    al, es:100h

This stores an arbitrary value in the least significant byte. Next you do:

mov    ah, 0

This zeroes out the most significant byte. Therefore ax is between 0 and 0xff.

Now you and it with the value 0xA0:

and    ax, 0A0h

And last you compare the ax register with the value 0x20:

cmp    ax, 20h

At no point in this series of operations does endianness factor into play. Consider:

mov    al, es:100h ;         ax = ???? ???? ???? ????
mov    ah, 0       ;         ax = 0000 0000 ???? ????
and    ax, 0A0h    ;         ax = 0000 0000 ?0?0 0000
cmp    ax, 20h     ; compare with 0000 0000 0010 0000

Alternatively we can write this with the bytes reversed so that the most significant byte is to the right:

mov    al, es:100h ;         ax = ???? ???? ???? ????
mov    ah, 0       ;         ax = ???? ???? 0000 0000
and    ax, 0A0h    ;         ax = ?0?0 0000 0000 0000
cmp    ax, 20h     ; compare with 0010 0000 0000 0000

As you can see you should get the exact same result regardless of endianness.

Kaiting Chen
  • 1,076
  • 1
  • 7
  • 12
1

Endian-ness only matters when fetching multi-byte values from memory. In your example, the first line fetches a single byte from memory, so endian-ness is not an issue.

When you hard-code constants in assembly, they read from left to right, just like normal numbers. So the constant 0A0h has 00000000 as the high byte (corresponding to ah) and 10100000 as the low byte (corresponding to al).

You do seem to be confused about the number of bits in the register. AX is a sixteen bit register. So the commenting the code using binary, the comments should be

mov    al, es:100h  ; ax = ???? ???? ???? ????
mov    ah, 0        ; ax = 0000 0000 ???? ????
and    ax, 0A0h     ; ax = 0000 0000 ?0?0 0000
cmp    ax, 20h      ; compare with 0000 0000 0010 0000
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • Actually, depending on what flags are tested after the `cmp`, it could be doing multiple things. e.g. `jg` would branch if `al` was `0x80` or `0xA0`. `jge` would branch if either bit was set (in which case the `cmp` is redundant, and `jnz` after the `and`, or after `test al, 0A0h` would do it.) – Peter Cordes Aug 04 '15 at 20:46
  • @PeterCordes Good point, I changed the last comment to be more generic :) – user3386109 Aug 04 '15 at 20:48
0

AFAICT, the mov ah, 0 has no effect on the flags after the cmp. The top half of ax is already zeroed by the and ax, 0A0h.

Depending on what condition you want to branch on, the flags set by the and might be sufficient. You left out the next instruction, so we can't tell you what the code is actually testing, and whether it could have been done with just a test instead of and / cmp.

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