Author Topic: Pointers in NASM  (Read 23041 times)

nobody

  • Guest
Pointers in NASM
« on: December 30, 2008, 07:04:56 PM »
Well, I'm reading the 16-bit Dos version of the book "Art Of Assembly" that uses MASM. In chapter 5 it describes the use of pointers like this:

Ptr1 near ptr word ?
Ptr2 near ptr word K ;Initialize with K's address.
Ptr3 far ptr word L ;Initialize with L's segmented adrs.

Where K and L are variable arrays in memory. And later in the same chapter it goes to show how to use Ptr1, Ptr2 and Ptr3 to point into something.

But it is my understanding that under NASM you cannot use the word ptr, am I correct?

So I tried to do it a different way. Let's say we have an array variable 'K' and a variable 'KPtr' (that we use to point to variable K later) declared in data segment as follows:

SEGMENT data

K   db 30H, 31H, 32H
   KPtr   resw 1

now I thought I'd put KPtr to point to K like this:

mov   AX, K
   mov   WORD [KPtr], AX
   mov   DL, [KPtr]
   call   DisplayChar
   add   BYTE [KPtr], 01H
   mov   DL, [KPtr]
   call   DisplayChar
   mov   DL, [KPtr+1]
   call   DisplayChar
   mov   DL, [KPtr+2]
   call   DisplayChar

mov   AX, 4C00H
   int   21H

(Don't mind about DisplayChar, it's just a function for displaying a character stored in DL into monitor)

I thought, if I move the address of K first into AX, with
mov AX, K
and then move the contents of AX into [KPtr]
mov WORD [KPtr], AX
I would have a variable called KPtr with an address to an array variable K as it's value, and then I could use KPtr as a pointer to manipulate the array variable K.

But it doesn't work
if I write
add   BYTE [KPtr], 01H
the first element of K doesn't change.
and when I write
mov   DL, [KPtr]
call   DisplayChar
The program displays just trash into monitor, and not what I originally intended it to display (in this case that would be "o" before the add instruction and "1" after the add instruction).

So a question remains: Can anyone explain to me how I use pointers in NASM? it seems that MASM and TASM make using pointers very simple, but I just can't figure out how to do it with NASM.

EDIT: now that I look at it again, I see that after
        mov   AX, K
   mov   WORD [KPtr], AX
[KPtr] just holds a value of the address of K, and it doesn't actually point to K. So I realize that the little program I wrote doesn't do at all what I intended it to do. But I just can't figure out how I can make it do what I actually intended it to do. Is there anyone who can help me? I know that i'm very new to NASM, but I would very much like to learn to code with it.

Debbie Wiles

  • Guest
Re: Pointers in NASM
« Reply #1 on: December 31, 2008, 12:43:11 AM »
Hi Anonymous

I'll comment the code you wrote, then I'll rewrite with comments to show how easy what I think you are doing is when you know the syntax. Sometimes using a tutorial such as Art Of Assembler is only good if you already either know something or use the tools the book recommends...

>SEGMENT data

>K db 30H, 31H, 32H                         ; initialise K with an array of 3 byte values
>KPtr resw 1                                     ; reserve space at KPtr for a p16-bit pointer to K

>now I thought I'd put KPtr to point to K like this:
>
>mov AX, K                                       ; Load AX with the address of K
>mov WORD [KPtr], AX                     ; Load the 16-bit space at KPtr with the address of K
>mov DL, [KPtr]                                 ; Load DL with the low byte of the address of K
>call DisplayChar                              ; display random character based on the address of K
>add BYTE [KPtr], 01H                      ;
>mov DL, [KPtr]                                ; a** you see, the following code will also be loading, reading, displaying the wrong info...
>call DisplayChar
>mov DL, [KPtr+1]
>call DisplayChar
>mov DL, [KPtr+2]
>call DisplayChar
>
>mov AX, 4C00H
>int 21H

What I believe you are trying to do does not need KPtr:

K db 30H, 31H, 32H                          ; initialise K with an array of 3 byte values

mov AX,K                                           ; Load the address of K into BX
mov DL, [BX]                                       ; Load the byte at K into DL (ie load 30h, in this case)
call DisplayChar                                ; display 30h
inc byte [K]                                       ; add 1 to the first byte at K
mov DL, [BX]                                     ; load the new value at K into DL
call DisplayChar                                ; display character
mov DL, [BX+1]                                 ; etc
call DisplayChar                                  ; etc
mov DL, [BX+2]                                  ; etc
call DisplayChar                                  ; etc

mov AX, 4C00H
int 21H

This code will write the byte at K, increment it then write 3 bytes starting from K. If that is not what you are looking for, please explain a bit more so we can help you to work out how to modify what I wrote :)

Debs

Debbie Wiles

  • Guest
Re: Pointers in NASM
« Reply #2 on: December 31, 2008, 12:44:22 AM »
Oops, first line of code above should have read:

mov BX,K ; Load the address of K into BX

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Pointers in NASM
« Reply #3 on: December 31, 2008, 02:48:51 AM »
Hi nobody... Hi Debs! - Hey, nobody, you lured Debs into the discussion! Kewl!!!

Drat, you fixed your typo before I got to it. Gotta be quick! :)

I'm going to give a different answer, though. The trick is "dereferencing the pointer"... (I think that's what they call it over at the University)

SEGMENT data

K db 30H, 31H, 32H
KPtr resw 1

Strictly speaking, you shouldn't use "res*" in an initialized section. In "-f obj" output format, Nasm lets it slide, but in any(?) other output format, it wails, "Attempt to reserve space in an uninitialized segment - zeroing" (or some such). It's a worse problem to attempt to initialize data/code in an uninitialized section (".bss", in output formats that "know" that name - Masm calls it ".data?", I think). Nasm truely "ignores" that! Since I don't know how to create an uninitialized section in Nasm (except a section with all "res*" data, if it's last, doesn't add anything to the file size), let it go - "dw 0" would do the same thing...


> now I thought I'd put KPtr to point to K like this:

You don't show the "mov ax, data"/"mov ds, ax" part. I assume you do so...


mov AX, K
mov WORD [KPtr], AX

So far, so good... You could also have initialized it: "Kptr dw K"...

mov DL, [KPtr] ; RONG

But *this* moves the low byte of the address of K into dl, not the byte at [K]!

mov bx, [Kptr]
mov dl, [bx]

(can't be "just any register", for 16-bit instructions, must be bx, si, or di - bp would work, but [bp] defaults to [ss:bp] and we'd have to use an override - [ds:bp]. 16-bit "effective address" rules are a royal PITA - being able to forget 'em is the best thing about graduating to 32-bit code!)

call DisplayChar
add BYTE [bx], 01H
mov DL, [bx]
call DisplayChar
mov DL, [bx+1]
call DisplayChar
mov DL, [bx+2]
call DisplayChar

mov AX, 4C00H
int 21H

As Debs points out, you don't really need "Kptr" for this - don't really need bx, either, "mov dl, [K + 1]", etc. would also work. But remember that "Kptr" is the address of Kptr, [Kptr] is the "[contents]" of Kptr - the address of K. "[[Kptr]]" won't work to give us the contents of K, however! Gotta do the "mov reg, [Kptr]"/"mov dl, [reg]" thing. In Masm, things are different: "Kptr" means "[contents]", "offset Kptr" is the address. The actual "ptr" keyword is "syntactic fluff" that doesn't do a damn thing - what else would it be???

I've been known to tell people reading AoA that it's okay to use Masm - just wash your hands after! :) These days, there's a better solution (if your objections to Masm are "political"). Japheth has forked OpenWatcom's Wasm into Jwasm - more compatible with Masm. I *think* it should be a drop-in replacement for Masm...

http://www.japheth.de/JWasm.html

It even does ELF, so it's *better* than Masm - you don't even need to use their damn OS! The syntax is still uglier than ours, though. :)

Best,
Frank