I can't get my pointers in assembly to work, I'm using nasm and trying to use pointers in real mode with 16-bit registers. Here is my code:

mov di, Pointer
mov ah, 0x0e
mov al, [di]
int 0x10

Pointer:
db "W"

This code should print out the character "W" using the DOS function 0x0e of interrupt 0x10.
I't always prints out instead, a different character that is the same no matter what I make the pointer "Pointer"'s value point to.
So what did I do wrong?

Recommended Answers

All 11 Replies

Programs in DOS start from address 0x100, right? You'll need this at the top of your code:

ORG 0x100

Programs in DOS start from address 0x100, right? You'll need this at the top of your code:

ORG 0x100

Wow thanks, that worked, but can you please explain to me why I need to do that?
What I am mainly looking for is what is the assembler doing that makes it require that?
-Is is because when you specify you labels those labels only tell you how far the label is from the start of your code, there for I need to add on the offset of where the code is located in memory?

Wow thanks, that worked, but can you please explain to me why I need to do that?
What I am mainly looking for is what is the assembler doing that makes it require that?
-Is is because when you specify you labels those labels only tell you how far the label is from the start of your code, there for I need to add on the offset of where the code is located in memory?

Yeah, pretty much like that. DOS loads your program to address 0x100. When you assemble your code, NASM automatically assumes that your code will be loaded to address 0. So when you refer to the label in your code, NASM assumes the label will point to address X, while the label will actually be located at address 0x100 + X. Using the ORG directive, we tell NASM where our code will be loaded by DOS (ORG stands for origin). Hope that made things clear! ;)

Yeah, pretty much like that. DOS loads your program to address 0x100. When you assemble your code, NASM automatically assumes that your code will be loaded to address 0. So when you refer to the label in your code, NASM assumes the label will point to address X, while the label will actually be located at address 0x100 + X. Using the ORG directive, we tell NASM where our code will be loaded by DOS (ORG stands for origin). Hope that made things clear! ;)

Yes, that did clarify things. I have one more question, how would I get my code to detect were it is located in memory, so it can be placed in memory anywhere and still work?

Yes, that did clarify things. I have one more question, how would I get my code to detect were it is located in memory, so it can be placed in memory anywhere and still work?

You do not need to worry about that. Where your program will be placed in memory is calculated when the program is linked, or on some systems, when the program is loaded. Except for very old systems (such as DOS), where the programmer must tell the assembler.

Only the operating system can determine where a program is loaded because there are probably other programs in memory whose address may conflict the the one you specify. The program loader reads the program into memory, finds out where to store it, then resolves all program addresses to actual physical address, such as resolves the addresses of all call statements. Even MS-DOS 6.X and earlier work that way because of TSRs (Terminate and Stay Resident, which are the grandfather of modern device drivers).

You do not need to worry about that. Where your program will be placed in memory is calculated when the program is linked, or on some systems, when the program is loaded. Except for very old systems (such as DOS), where the programmer must tell the assembler.

I realize this, because due to paging each program's memory always starts at memory location 0, relative to the pages actual location in memory. Although I was just wondering if there is a way to get the memory location of your program in memory. Also insted of adding an "ORG 0x100" could this work:

mov si, Pointer
mov ah, 0x0e
mov al, [0x100:si]
int 0x10

Pointer:
db "W"

or as by using a register for the memory location:

mov di, 0x100
mov si, Pointer
mov ah, 0x0e
mov al, [di:si]
int 0x10

Pointer:
db "W"

Almost, however since your using Segment:Offset addressing, you will need to make the left side (the segment number) 0x10 (since the address is SEGMENT * 16).

Almost, however since your using Segment:Offset addressing, you will need to make the left side (the segment number) 0x10 (since the address is SEGMENT * 16).

Ok, could I also do it like this "mov [si + 0x100]" since it is not an segment:offset it stays as 0x100 correct?

Yes, I think that should work

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.