Author Topic: DW and DB difference  (Read 11543 times)

Offline Sana Ullah

  • Jr. Member
  • *
  • Posts: 2
DW and DB difference
« on: March 18, 2015, 04:40:21 PM »
What is the main difference in these two examples i m new to ASM  :-\

Code: [Select]
[org 0x300]
mov ax,[num1]
mov [num1+3],ax
mov ax,[num1+1]
add [num1+3],ax
mov ax,[num1+2]
add [num1+3],ax

mov ax,0x4c00
int 0x21

num1: db 5, 10, 15, 0

Code: [Select]
[org 0x300]
mov ax,[num1]
mov [num1+6],ax
mov ax,[num1+2]
add [num1+6],ax
mov ax,[num1+4]
add [num1+6],ax

mov ax,0x4c00
int 0x21

num1: dw 5, 10, 15, 0

Offline encryptor256

  • Full Member
  • **
  • Posts: 250
  • Country: lv
  • Win64 .
    • On Youtube: encryptor256
Re: DW and DB difference
« Reply #1 on: March 18, 2015, 05:44:08 PM »
DW - Define word
DB - Define byte

DB -----------------------
num: db 5
Define 5 which is 8 bit number (in 8 bit range).
OR
Define 8 bit number with initial value 5.

DW -----------------------
num: dw 5
Define 5 which is 16 bit number (in 16 bit range).
OR
Define 16 bit number with initial value 5.

Encryptor256's Investigation \ Research Department.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: DW and DB difference
« Reply #2 on: March 18, 2015, 09:57:55 PM »
Hi Sana,

Thanks for joining us!

Can I say "charlie foxtrot" on the forum? I'd better not. I didn't say that.
Quote
What is the main difference in these two examples
The first one is even more massively wrong than the second one! Neither is likely to do anything useful.

We better start at the beginning. Encryptor256 has explained the difference between "db" and "dw". Did you understand it? We'll get back to that. But first...
Code: [Select]
[org 0x300]
We usually ask you, right off, "What OS?" Since you use "int 0x21", with a subfunction number in ah which would "return to DOS", I'm going to ASSume DOS.

The "origin" (abbreviated "org" rather than "ori" for "historical reasons", I guess) does not "cause" your code to be loaded at that address. It merely informs Nasm that the code will be loaded at that address. I hope you understand that "num1", your variable name, does not go into the machine code (which is what your CPU runs). It is replaced by the address (the offset part of the full segment:offset address, strictly speaking). To calculate this address, Nasm adds the "org" number to the file offset of the variable. Since DOS will load a .com file at "org 0x100", Nasm is going to calculate an incorrect address for this! When you refer to "[num1]", you're loading some memory "off in the weeds" - not where you put your numbers! (unless you're using a custom loader which actually loads your code at 0x300 - possible, but improbable).

ASSuming we've got that fixed, one way or the other, we can get back to the difference between "db" and "dw"...
Code: [Select]
mov ax,[num1]
Some assemblers "remember" that you said "num1" was "db" (bytes) and would barf up an error messages for this. Nasm has amnesia, and does not "remember" that "num1" is supposed to be bytes, and will obediantly do what you told it to do - which is to load both [num1] and [num1 + 1] into ax - a "word (16 bits) register. So ax will be 0x0a05 or 2565 decimal - probably not what you intend (although perfectly "legal"). You probably want to do:
Code: [Select]
mov al, [num1]
so that the size of the register (8 bits = 1 byte) matches the size of the number you defined with "db". Then al would be 5, as you probably intend.

Then it gets worse...
Code: [Select]
mov [num1+3],ax
Since you used a 16-bit (two byte) register, this will put the first byte (the 5) into [num1 +3] (overwriting the 0), and the second byte (the 0xA or 10 decimal) into [num1 + 4]. [num1 + 4] is beyond the end of your variable! Since there's nothing after it, this won't do any actual harm, but it definitely isn't "right"! If there had been another variable after "num1", you would have just scribbled on top of it.
Code: [Select]
mov ax,[num1+1]
Now we move another two bytes - at [num1 + 1] and [num1 + 2] - into ax. So ax is 0x0F0A (3850 decimal).
Code: [Select]
add [num1+3],ax
We add this value to [num1 + 3] and [num1 + 4] (the "illegal" byte that's past the end of our array). So memory looks like 5 0xA 0xF 0xF 0x19 (with the last byte outside of our array).
Code: [Select]
mov ax,[num1+2]
We load another two bytes into ax - the 0xF (15) that was in [num1 + 2], and 0xF (15) in [num1 + 3] - we overwrote the 0 that was there with the first store and the first add. So ax is 0xF0F.
Code: [Select]
add [num1+3],ax
We add that to [num1 + 3] and [num1 + 4] (which is "some other variable"... but nobody else was using it). So memory looks like 5 0xA 0xF 0x1E 0x28.

If you'd used al instead of ax up to here - matching the one byte you defined the numbers, it would probably do more like what you'd expect. Then, back to DOS.
Code: [Select]
mov ax,0x4c00
int 0x21

num1: db 5, 10, 15, 0

The second example is more nearly correct - outside of the "org" being "wrong"... or "strange" at least. You've defined your numbers as "dw" (two bytes, 16 bits) and you're using a word (16 bits) register to access them. The actual bytes in memory originally look like: 5 0 0xA 0 0xF 0 0 0 - so grabbing two bytes into ax is what you want. Note that we're on a "little endian" machine - in a multi-byte number, the least significant byte is stored first in memory, more significant bytes come later. This applies only to multi-byte numbers - it does not mean that "hello world" gets stored backwards!

... and that's the practical difference between "db" and "dw"...

Best,
Frank


Offline Sana Ullah

  • Jr. Member
  • *
  • Posts: 2
Re: DW and DB difference
« Reply #3 on: March 24, 2015, 08:40:15 AM »
Frank Kotler - it was very helpful i got the idea  :D