Author Topic: Passing variable addresses with CALL  (Read 2032 times)

0 Members and 1 Guest are viewing this topic.

Offline zeebee

  • CPC464
  • **
  • Posts: 6
  • Liked: 1
  • Likes Given: 0
Passing variable addresses with CALL
« on: 23:24, 19 January 12 »
Hi all,

I am trying to pass the address of a string variable from BASIC to a small machine code program. I am learning about IX and IY.

When I pass:

a%=42
CALL &4000,@a%

The address pointed to by IX contains the address of the 'a' variable in memory, where BASIC is keeping it, so I can read and modify it through IX.

But when I do:

a$="hobbits"
call &4000,@a$

The address pointed to by IX does not contain the address of this string variable in memory. I found the string somewhere else in memory, and I don't know how to get this variable's address in my assembly code.

I have tried on both WinAPE and WinCPC emulators, I don't have a real Amstrad (yet!).

Am I doing something obviously wrong?

Thanks.

Offline ralferoo

  • Supporter
  • 6128 Plus
  • *
  • Posts: 970
  • Country: gb
  • Liked: 583
  • Likes Given: 222
Re: Passing variable addresses with CALL
« Reply #1 on: 23:50, 19 January 12 »
Try something like this:
Code: [Select]
ld e,(ix+0)
ld d,(ix+1)
push de
pop iy
ld a,(iy+0)    ; A=length
ld l,(iy+1)
ld h,(iy+2)    ; HL=address
The last parameter will be at (IX+0/1), the second to last at (IX+2/3) etc... A at entry holds the number of parameters.

The simplest way of thinking about it is that BASIC pushes each parameter onto the stack and then does LD IX,0:ADD IX,SP before calling your code.
« Last Edit: 23:54, 19 January 12 by ralferoo »

Offline zeebee

  • CPC464
  • **
  • Posts: 6
  • Liked: 1
  • Likes Given: 0
Re: Passing variable addresses with CALL
« Reply #2 on: 00:23, 20 January 12 »
Yes, and this works as you describe for the a% case, but not for strings, i.e. a$

BASIC:

a$="hobbits"
call &4000,@a$

z80:

org &4000
limit &4fff
ld e,(ix+0)
ld d,(ix+1)
push de
pop iy
ld a,(iy+0)    ; A=length
ld l,(iy+1)
ld h,(iy+2)    ; HL=address
ret

A does contain the number of parameters, 1. ED is not loaded with the address of "hobbits" in memory, when I pass the address of a string (a $ var) - it only works when I pass numbers (% vars).

In your example, if it worked, I would expect to get the ASCII values for 'h', 'o', and 'b' loaded into A, L, and H respectively. This is not the case because the address pointed to by IX and pushed onto the stack does not point to "hobbits" where it is kept in memory by BASIC.

So, does this work on a real machine?

[I can't believe WinAPE and WinCPC would have this wrong so it must be me :D ]


Offline zeebee

  • CPC464
  • **
  • Posts: 6
  • Liked: 1
  • Likes Given: 0
Re: Passing variable addresses with CALL
« Reply #3 on: 00:43, 20 January 12 »
There seems to be an extra level of indirection when string variables are passed, and a strange offset of one byte.

This works for me (under WinAPE):

org &4000
limit &4fff
ld e,(ix+0)
ld d,(ix+1)
inc de
ld a,(de)
ld l,a
inc de
ld a,(de)
ld h,a
push hl
pop iy
ld a,(iy+0)
call &bb5a    ;'h'
ld a,(iy+1)
call &bb5a    ;'o'
ld a,(iy+2)
call &bb5a    ;'b'
ret

I have to INC the address in IX by one byte, and read the two bytes at that location as another address - the address of my string!? Contrast this with passing in numeic vars (%), where IX is the actual address of that variable in memory.

I know C, so the address of a string being a ptr to a ptr doesn't surpise me, but I do not understand IX being one byte out ...


Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.336
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2278
  • Likes Given: 3478
Re: Passing variable addresses with CALL
« Reply #4 on: 11:50, 20 January 12 »
Hi all,

I am trying to pass the address of a string variable from BASIC to a small machine code program. I am learning about IX and IY.

When I pass:

a%=42
CALL &4000,@a%

The address pointed to by IX contains the address of the 'a' variable in memory, where BASIC is keeping it, so I can read and modify it through IX.

But when I do:

a$="hobbits"
call &4000,@a$

The address pointed to by IX does not contain the address of this string variable in memory. I found the string somewhere else in memory, and I don't know how to get this variable's address in my assembly code.

I have tried on both WinAPE and WinCPC emulators, I don't have a real Amstrad (yet!).

Am I doing something obviously wrong?

Thanks.
In this case, IX points to a "string descriptor". This is a 3-byte structure with string length (1 byte), string address (2 bytes).
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline zeebee

  • CPC464
  • **
  • Posts: 6
  • Liked: 1
  • Likes Given: 0
Re: Passing variable addresses with CALL
« Reply #5 on: 01:02, 21 January 12 »
Thanks. That is exactly the case. :)

Offline ralferoo

  • Supporter
  • 6128 Plus
  • *
  • Posts: 970
  • Country: gb
  • Liked: 583
  • Likes Given: 222
Re: Passing variable addresses with CALL
« Reply #6 on: 14:26, 21 January 12 »
In your example, if it worked, I would expect to get the ASCII values for 'h', 'o', and 'b' loaded into A, L, and H respectively. This is not the case because the address pointed to by IX and pushed onto the stack does not point to "hobbits" where it is kept in memory by BASIC.
You clearly didn't read the comments in my Z80 code where I said that A is the length and HL is the address of the string. Here it is again:  ;)
Code: [Select]
ld a,(iy+0)    ; A=length
ld l,(iy+1)
ld h,(iy+2)    ; HL=address
Your example is just moving the address from HL to IY in order to read the characters. Alternatively, you could have done something like this at the end of my code to print the entire string:
Code: [Select]
or a
ret z       ; return if empty string
ld b,a
print_loop:
 ld a,(hl)
call &bb5a
inc hl
djnz print_loop

Offline zeebee

  • CPC464
  • **
  • Posts: 6
  • Liked: 1
  • Likes Given: 0
Re: Passing variable addresses with CALL
« Reply #7 on: 17:18, 21 January 12 »
Sorry, I didn't understand your reply from the code alone. The other poster said it in just such a way that I got it.


As you can see form my code snippet, I am very new to assembly. :)


You example for printing out the string works perfectly and is much neater than my own. Thankyou.

Offline ralferoo

  • Supporter
  • 6128 Plus
  • *
  • Posts: 970
  • Country: gb
  • Liked: 583
  • Likes Given: 222
Re: Passing variable addresses with CALL
« Reply #8 on: 02:55, 22 January 12 »
Heh, not a problem. Good luck in learning Z80... if you have questions, feel free to ask as there are quite a few coders on here!

Also, one of the best ways of learning is to take a look at other people's code, preferably with some comments, and try to figure out how it works...