Why is my assembly code skipping a line? It keeps skipping the line mov AX,A
org 100h
count equ 2
A DW 5
B DW 6
Y0 DW ?
Y1 DW ?
mov AX,A
ad
Let's see what code bytes these instruction mnemonics would assemble to:
org 100h
count equ 2
05 00 A DW 5
06 00 B DW 6
00 00 Y0 DW ?
00 00 Y1 DW ?
A1 00 01 mov AX,A ;NASM "mov ax, [A]"
03 06 02 01 add AX,B ;NASM "add ax, [B]"
83 E8 02 sub AX,count
...
The code bytes are on the left; the instruction mnemonics (the part you feed to the assembler) are on the right. All looks good, right?
Well, now let's see what happens when we assemble and then disassemble the code:
05 00 06 add ax,0x600
00 00 add [bx+si],al
00 00 add [bx+si],al
00 B8 00 01 add [bx+si+0x100],bh
05 02 01 add ax,0x102
83 E8 02 sub ax,byte +0x2
Wait…what happened?! The bytes (on the left) are the same, but the instruction mnemonics are all different! They're not the same ones you originally wrote!
What happened is, the data declarations that were at the top of your code were all dutifully translated into bytes by the assembler, but then the disassembler translated those (data) bytes back into executable code. It didn't realize they were data, so it tried to interpret them as instructions to be executed. This resulted not only in the incorrect instructions, but also introduced a frameshift mutation that messed up everything downstream.
So it's not actually "skipping" the instruction mov ax, a
. That instruction isn't even there anymore, as far as the computer can tell. It is executing the instructions that you see in the second block of code. Basically, it is executing nonsense. Remember: in assembler, everything is just bytes!
The solution should be obvious: don't mix data declarations in with your executable code. The best thing to do would be to move the data down to the bottom, below all of your executable code, where execution will never get:
org 100h
count equ 2
mov AX,A
add AX,B
sub AX,count
mov Y0,AX
mov BX,B
neg BX
add BX,count
mov Y1,BX
ret
A DW 5
B DW 6
Y0 DW ?
Y1 DW ?
Introducing whitespace helps to break things up into logical chunks, making the code more readable. Notice that I've left the ORG
directive at the top, because it needs to be there. I also didn't move the EQU
directive to the bottom. It's okay to leave that there because it just defines an assemble-time constant. As you can see from the very beginning, it isn't translated into any bytes in the resulting machine code.
If you didn't want to move the data for whatever reason, then you would have to insert an instruction to jump over it:
org 100h
count equ 2
jmp Begin
A DW 5
B DW 6
Y0 DW ?
Y1 DW ?
Begin:
mov AX,A
add AX,B
sub AX,count
mov Y0,AX
mov BX,B
neg BX
add BX,count
mov Y1,BX
ret
The problem is that in your code you have mixed operation codes with data definitions. This is completely wrong, due to the fact that your Assembler is going to assume that these data definitions are mnemonics, messing around the code. To see it just download a Hex Editor and see the Hex format of your code. Then find a Disassembler and try to disassemble the hex formated code. You will see that the code shown by the Disassembler will be way more different from what you have typed in your code. In other words the linemov AX, A
is not skipped, rather than assumed to be another op code.