×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Quick Q on [ ] ...

Quick Q on [ ] ...

Quick Q on [ ] ...

(OP)
ok...

mov bp, sp
moves the address of sp to the address of bp...
...

mov ax,[bp+06]
moves the value at bp + 6 into ax
...

but what is the difference in these to commands...
mov bx, ax
 - and -
mov [bx],ax
???

Here is the code context this was found in...
PUSH    BP
MOV    BP,SP
MOV    BX,[BP+0C]
MOV    AX,[BX]
PUSH    AX
MOV    BX,[BP+0A]
MOV    AX,[BX]
PUSH    AX
MOV    BX,[BP+08]
MOV    CX,[BX]
MOV    BX,[BP+06]
MOV    DX,[BX]
POP    BX
POP    AX
PUSH    DS
POP    ES
INT    33
PUSH    BX
MOV    BX,[BP+0C]
MOV    [BX],AX
POP    AX
MOV    BX,[BP+0A]
MOV    [BX],AX
MOV    BX,[BP+08]
MOV    [BX],CX
MOV    BX,[BP+06]
MOV    [BX],DX
POP    BP
RETF    0008


...which is a mouse routine commonly used in QBasic

Thanks for your help in advance, -Josh

Have Fun, Be Young... Code BASIC
-Josh Stribling

http://cubee.topcities.com

RE: Quick Q on [ ] ...

No worries, this one is not too difficult.
Anything in [] is an address, or more specifically an offset. So bx is simply the bx register, and
mov bx, ax
will put the contents of the ax register in the bx register.
But [bx] is the memory location pointed to by bx, so
mov [bx], ax
will put the contents of the ax register in the memory location pointed to by bx. So if bx contains 0300h, then the contents of ax will land up in memory location of offset 0300h.
The only remaining question is where the segment bit of the address comes from. If it is not stated specifically, there are various defaults. Normally anything will be regarded as in the data segment UNLESS you are using sp or bp, which are assumed to point to things in the stack segment.
Therefore
mov [bx], ax
is the same as
mov ds:[bx], ax
Assemblers tend to be a bit un-rigorous about how they enforce square brackets, so you can often get away with
mov ds:si, ax
as being the same as mov ds:[si], ax. But this is evil, and ideally would produce an error. I personally like to include the [] wherever specifying an offset, and often also the ds, even though it is unnecessary. To my mind, it makes the code clearer.
Helpfully, you can override the defaults and use a different segment, so
mov cs:[bx], ax
is perfectly OK (but a byte longer and a little slower, because the instruction involves a "segment override prefix").
Hope that helps!

PS
If you want, there are more complicated ways of addressing things in square brackets. In a 32 bit instruction (and surprisingly this can be done even in a non-protected 16 bit piece of code!) you can have something like
mov ax, es:[bx + 2*si]
But things are quicker if you can avoid this sort of complication.

RE: Quick Q on [ ] ...

(OP)
Ok, so is...
MOV    BX,[BP+06]
MOV    AX,[BX]

the same thing as...
MOV AX,[BP+06]

???

or does it work like this...

Say BP pointed to offset 00, and offset 06 contained to value: 123d

where BX = the value at [BP+O6]
MOV BX,[BP+06]  ==  MOV BX, 123d

then AX = the Value at the address of the value at [BP+06]
MOV AX,[BX]     ==  MOV AX, [123d]  == ???

-----------
also, isn't CS the Code Segmennt where your program is stored, and used internally with IP to execute the code CS:[IP] ...
so in the statement:
>>mov cs:[bx], ax
did you mean:
mov ds:[bx], ax

Or is there ever a time where you write to CS?

aren't the segements as followed...
CS : Code Segment
DS : Data Segment
ES : Extra data Segment
-- 32 bit --
FS : 32 additional segment
GS : 32 additional segment

...and [bp+06] defaults to ds:[bp+06]

Have Fun, Be Young... Code BASIC
-Josh Stribling

http://cubee.topcities.com

RE: Quick Q on [ ] ...

mov bx, [bp+06]
mov ax, [bx]
is not the same as mov ax, [bp+06]; in fact it works like you described with your example using 123d.
The bp addressing in [bp+06] will be taken from the stack segment, so written more fully it could have been
ss:[bp+06]
bp is an exception in this. Everything else (except sp, which you will probably rarely use) is assumed to be in ds.
Thus the [bx] will be relative to the data segment. So what's actually happening is you are taking an address from the stack, and using that address in the data segment. This is quite common. The stack is often used by high level languages for passed parameters and local variables, so the sort of code you wrote would happen if you called a function in a high level language which uses an address to something as one of its parameters. It is then using this address to look up something in the data segment.
bp was originially intended as a way of getting at stack-stored local variables etc.

You're quite right in your summary of segment useage. I gave the cs example to show segment overrides where you use a non-default segment. In non-protected code there is no reason why you shouldn't write in the code segment, except that purists will shout at you. In fact in a tiny model program, cs = ds. I only use cs for writing in (a) self-modifying code (horrors!), or (b) very small bits of tiny-type code, where I only refer to a variable once, and can't be bothered to set ds to cs for the purpose.

You can use fs and gs outside 32 bit code, just like es, but they cost a segment override prefix which is extra code and extra execution time (though not much of each!). They were introduced (I think) with the 386, so you're probably OK to use them anywhere now.

Have fun!

RE: Quick Q on [ ] ...

for your information

i put an FAQ that points to a url where you can download some intel manuals on the 80x86 series processors.

they are a must for all assembly programmers as the manuals go deeply in all the commands and usage.

one section is dedicated on index and addressing modes and which optimizations can be performed to make your code more efficient.

these manuals explain everything - as far as assembly is concerned, ive never had to go beyond them myself.

straiph

"There are 10 types of people in this world, those who know binary and those who don't!"

RE: Quick Q on [ ] ...

(OP)
ok...

BASIC has 2 ways to pass variables...
  ByVal : By Value...
  ByRef : By memory reference...

when you pass params to asm in qb, such as:
CALL ABSOLUTE (A, B, C, SADD(ASM))
The stack looks like this...
  00 : BP (see below)
  02 : QB return segment
  04 : QB return offset
  06 : param C
  08 : param B
  0A : param A

So when you use...
  PUSH BP
  MOV BP,SP

the Base Pointer points to the Stack Pointer...
So [BP+06] contains the (last) value that is passed to the routine...

so if you pass the variable to the asm routine with byval,
you just use...
  PUSH BP
  MOV BP,SP
  MOV AX,[BP+06]

Since [bp+06] already contains the value...

But...
If you pass with ByRef, You have to use...
  PUSH BP
  MOV BP,SP
  MOV BX,[BP+06]
  MOV AX,[BX]

since the value only contains the reference to the memory location where the variable is, so you still have to use [BX] to obtain the actual value...

Right?

also, is this legal...
  PUSH BP
  MOV BP,SP
  MOV AX,[BP+06]
  MOV AX,[AX]

where you mov the reference into AX then move the value at the reference in AX to AX, Or do you have to use another Register...

And... is it considered to be a better practice to do something similar to this (using SI or DI) instead of using [BX] for an offset...
  PUSH BP
  MOV BP,SP
  MOV SI,[BP+06]
  MOV AX,[SI]


One more thing...
Am I right, in assuming, [AX] or [BX] or [SI] ... used by them selfs, default to the current DS, where [AX] is actually DS:[AX] ?

Now with all of this said, I am assuming this is the way you can use QB arrays in asm... right?

In QB...
  VarSeg(var) returns the segment of a var...
  VarPtr(var) returns the offset pointer of var...

So, using...
CALL ABSOLUTE (varseg(array(0)), varptr(array(0)), SADD(ASM))

you can access the array like so...
  PUSH BP
  MOV BP,SP
  MOV SI,[BP+06]
  MOV ES,[BP+08]
  MOV AX,ES:[SI]
  MOV BX,ES:[SI+02]
  MOV CX,ES:[SI+04]

right???

Have Fun, Be Young... Code BASIC
-Josh Stribling

http://cubee.topcities.com

RE: Quick Q on [ ] ...

I think I haven't been very clear on what registers are OK in [], largely because I have got in the habit of only using them in certain ways. So for clarification, and I think this is correct:
In 16-bit mode etc., sorry, only si, di, bp, and bx can be used in [] as indexes.
In 32-bit extended-mode addressing other registers can be used. You can do this in 16-bit code, but only when referring to 32-bit registers, so it is OK in a 16-bit piece of code to refer to eax, ebx etc., and these can be used in funny indexing. Note, though, that any attempt to access memory outside the normal DOS 1MB will not work! That means that the only real use that 16-bit programmers make of indexed addressing using the full 32-bit stuff is in cheats like lea eax, [eax+eax*4] as a quick way to multiply by 5.
Otherwise, in normal 16-bit stuff, you can write
mov bx, [bx]
Hope that helps!

RE: Quick Q on [ ] ...

(OP)
Yeah, I think I read somrthing the other day about the other reason BX is the Base Register is because it can be used for indexing memory (16bit Doc for debug)... I wasn't sure if that was exclusive or not at the time...

lol... I bet that is why I could not get one of my programs to work the last time I tried to learn ASM a few years ago...

I think I was trying to mov from DS:[AX] to ES:[BX] or something similar to that...

Under "normal" conditions, you usually want to use SI with DS and DI with ES... right?

now...

do you have to use a register as a "middle man" ?

mov ax,ds:[si]
mov es:[di],ax

or can you mov straight from one to the other?

mov es:[di],ds:[si]

btw... you earned a star... again

Have Fun, Be Young... Code BASIC
-Josh Stribling

http://cubee.topcities.com

RE: Quick Q on [ ] ...

Thanks for your patience with my sometimes not totally accurate replies!

(1) Most people do seem to use ds:[si] and es:[di] combinations, but I'm not sure there's any rule about it. You certainly don't have to. I must admit I tend to, because it leaves me less to remember...

(2) No, you need the middle register. The "reason" is that the op-code contains 3 bits dealing with the indexed addressing, and 3 more bits somewhere else dealing with the other operand, and the two have a different format, so you can't have 2 lots of indexed addressing in a single instruction.

have fun!

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login


Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close