NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: tysonprogrammer on July 24, 2022, 08:29:45 PM
-
I am writing a program in x86 assembly for FreeDOS. I am trying to stick with 16 bit registers so it will work on older hardware.
The program will create a framed box on the screen and I am pushing a structure with the values for the box on the stack to a routine. I would like to know if I can store this stack value in a label. I am currently using si and that works fine but if I can not use si then I have use for other things. I know I can push it onto the stack to save it but if I don't have to the would be great.
I have the following structure defined.
struc BOX_FRAME
.TopX: resb 1
.TopY: resb 1
.BottomX: resb 1
.BottomY: resb 1
.Color: resb 1
endstruc
and this label defined in my data section
section data
window:
istruc BOX_FRAME
at BOX_FRAME.TopX, db 0
at BOX_FRAME.TopY, db 0
at BOX_FRAME.BottomX, db 0
at BOX_FRAME.BottomY, db 0
at BOX_FRAME.Color, db 0
iend
I am passing this on the stack using this
mov ax, data
mov ds, ax
mov [window+BOX_FRAME.TopX], byte 4
mov [window+BOX_FRAME.TopY], byte 4
mov [window+BOX_FRAME.BottomX], byte 25
mov [window+BOX_FRAME.BottomY], byte 10
mov [window+BOX_FRAME.Color], byte COLOR_YELLOW
or [window+BOX_FRAME.Color], byte COLOR_BLUE
push window
call drawWindow
in drawWindow I have this
drawWindow:
.init:
push bp
mov bp, sp
mov si, word [bp+4]
I have the following single-line macros defined
%define x1 byte [si+BOX_FRAME.TopX]
%define y1 byte [si+BOX_FRAME.TopY]
%define x2 byte [si+BOX_FRAME.BottomX]
%define y2 byte [si+BOX_FRAME.BottomY]
%define color byte [si+BOX_FRAME.Color]
Here is an example of how the single-line macros are used.
mdraw_corner x1, y1, BORDER_TOPLEFT
mdraw_corner is a multi-line macro
Using si works just fine but I am wondering if I can use a label instead. if so, how would I use it to address a value in the structure.
For example If I have a label defined
section bss
.draw_struct resw 1
I am attaching what it currently looks like when it runs, for your enjoyment and aww.
thanks much,
Tyson
-
Hi Tyson,
I may very well be confused!
You define a structure. Good.
You define an instance of the structure named "window". Only one, as far as I can see. This may be where I'm confused. You pass "window" to subroutines on the stack, but it's always the same instance of the structure... or I'm confused... You fill in different values in different subroutines, but always the same instance... IF I'm right. So there's no need to pass "window" and thus no need tp use si.
You could make a "local" ("automatic") instance of your structure on the stack...
mov bp, sp
sub sp, Box_Frame_size
; and make your instance in this space
mov sp, bp ; make it go away
but that's not what I think I see...
so:
%define x1 byte [window+BOX_FRAME.TopX]
;etc
without using si should work... I think...
But you may want to use different instances... or perhaps you do and I'm missing it. Depends on how confused I am. :)
Best,
Frank
-
Frank,
Thanks for your reply. Yes I could use the window instance since it is essentially global and maybe that's where I got off track coming for a OOP language. But just for giggles is there a way to use a reference label instead of si? Or is si used for that?
thanks,
Tyson
-
Sure. Use bx or di.
I don't think that's what you're looking for. I'm not sure what you are looking for.
foo equ bp + 4
?
Best,
Frank
-
You mean something like this?
bits 16
struc BOX_FRAME
.TopX: resb 1
.TopY: resb 1
.BottomX: resb 1
.BottomY: resb 1
.Color: resb 1
resb 1 ; To make it word sized.
endstruc
struc STK_FRAME
resw 1 ; return address
.wnd: resb BOX_FRAME_size
endstruc
; Yep... using cdecl convention:
;
; push window
; call f
; add esp,4
f:
; Why do you need to use 16 bits alias registers, even in 16 bit code?
; 386 registers and instructions are available!
mov al,[esp + STK_FRAME.wnd + BOX_FRAME.Color]
;...
ret
-
Dunno. Does it do what you want?
I think you might be better off to use si and quit fighting it... maybe...
Best,
Frank
-
My point: Instead trying to remember if you should add or subtract N from the stack pointer to access an argument pushed on stack, use structures... And more: Using BP to access the stack was wildely used on 8086 and 80286 because there were no other way to do it... Since 386 you can use ESP to access the stack directly.
The prologue/epilogue:
push bp
mov bp,sp ; prologue
...
pop bp ; epilogue
ret
Aren't necessary anymore, if you use ESP to access the stack.
Yep... ESP is 32 bits long, but in 16 bits mode the upper 16 bits os E?? will be discarded in an effective address calculation.
Of course, using ESP will add a prefix (0x67 maybe) and even a longer opcode, but this is faster then saving/retrieving BP to/from the stack.
The same argument can be made for using 32 bits registers as base/index on an effective address calculation, instead of the fixed [BX+(SI/DI)+offset]... Since we are free to use any registers (including repeating them) as base and index, the code tends to be shorter. And remember that 386+ has a scaling of indexes as well (not available on 80(2)86).
Simple example: Multiplying a register by 10:
; Multiply EAX by 10;
lea eax,[eax+eax*4] ; multiply by 5
shl eax,1 ; multiply by 2
This LEA isn't possible on pre-386 80x86 family processors. To do the same with AX on 8086 code:
mov cl,2
mov bx,ax
shl ax,cl ; There is no SHL AX,imm8 instruction on 80(2)86
add ax,bx
shl ax,1 ; except this one!
In general, using 32 bits registers on 16 bits code leads to better code.
[]s
Fred
-
Hi Fred,
Golly, I'm losing it! I didn't realize that it was you I was addressing last time.
I agree that 386 registers are way more convenient. Tyson says he wants to stick with 16-bit registers so it'll run on older hardware. In a museum? In the basement? Whatever.
But that's a slightly different question than accessing the stack through a label/ >aybr ovrtlaying the stack with a structure name as you show is what Tyson's looking for.
Best,
Frank
-
Hi Fred,
Golly, I'm losing it! I didn't realize that it was you I was addressing last time.
I agree that 386 registers are way more convenient. Tyson says he wants to stick with 16-bit registers so it'll run on older hardware. In a museum? In the basement? Whatever.
Hehehehehehehe... Maybe Tyson have a time machine and want to go back to the 1980's... I've seen "stranger things"... :)
But that's a slightly different question than accessing the stack through a label/ >aybr ovrtlaying the stack with a structure name as you show is what Tyson's looking for.
Maybe that helps...
[]s, Frank!
Fred
-
Hehehehehehehe... Maybe Tyson have a time machine and want to go back to the 1980's... I've seen "stranger things"... :)
Maybe I can hitch a ride with him. I was a young fellow in the 1980's. Not like now with my
memory all shot. :(
Best,
Frank
.
-
Thanks Fred and Frank
I will stick with si, it's just a pet project and I have no problem with 32-bit registers. Wish I had a time machine so I could go back and learn assembly at a much younger age :)
Yyson