Assembly two-dimensional array of pixels - arrays

How could I do something like this in assembly? DOS 16bit graphic mode
int start_x=1, start_y=1;
for(int i=0; i<8; i++){
for(int j=0; j<8; j++){
if(T34[i][j]==1) put_colour_pixel(start_x+i, start_y+j);
else put_black_pixel(start_x+i, start_y+j);
}
}
:edit:
So my loops pretty work. How to connect it to table with 0 and 1.
mov ax, 10 ; Y start line
mov bx, 20 ; X start line
mov dl, 4 ; colour (red)
mov cx, 5 ; loop top counter
top:
add ax, 1
push cx ;loop top counter
mov cx, 10
inside:
add bx, 1
push ax
push bx
push cx
call putpixel
pop cx
pop bx
pop ax
loop inside
mov bx, 20 ;next line X go to start X
pop cx ;loop top counter
loop top
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
My new code:
segment .data
segment .code
..start:
mov ax, 13h
int 10h ; switch to 320x200 mode
mov ax, 0a000h ; The offset to video memory
mov es, ax ; We load it to ES through AX,
; because immediate operation
; is not allowed on ES
;;;;;;;;;;;;;;;;;;;;;;
mov di, T34
mov si, 8
;------------------------------------
P1: mov bp, 8
;----------------
P2: cmp BYTE[di], 1
jnz short NOHIT
NOHIT: ; increase the x position
push ax
push bx
push cx
mov ax,si ;Y
mov bx,bp ;X
mov dl, 1 ; here I should take '0' or '1' from table
call putpixel
pop cx
pop bx
pop ax
inc di ; increase offset address of array
dec bp
jnz P2
;-------------
; increase the y position + substract 8 from x position
dec si
jnz P1
;------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;
xor ah, ah
int 16h ; keyboard (wait for key)
mov ax, 3
int 10h ; go to text mode
mov ax, 4c00h
int 21h ; return to DOS, exit code 0
;;;;;;;;;;;;;;;;;;;;;
putpixel:
push dx ; mul changes dx too
mov cx, 320
mul cx ; multiply Y (ax) by 320 (one row)
add ax, bx ; and add X (bx) (result= dx:ax)
mov di, ax
pop dx
mov [es:di], dl ; store color/pixel
ret
;;;;;;;;;;;;;;;;;;;;;;
T34 DB 1,1,1,1,1,1,1,1
DB 1,0,0,0,0,0,0,0
DB 1,0,0,0,0,0,0,0
DB 1,0,0,0,0,0,0,0
DB 1,1,1,1,1,1,1,1
DB 1,0,0,0,0,0,0,0
DB 1,0,0,0,0,0,0,0
DB 1,1,1,1,1,1,1,1
I have changed order and now it is drawing square in left corner (as I expected). Did I change order rigth?
I suppose that letter will be spinned, but it is not problem for me. I can fix it later.
Now I should go to '0' or '1' in table and set color. Which register have "0" or "1"?
So mostly I have problem with colour.
I have try this, but I have error. I have try set colour black (0) or blue (1)
push dx
mov ax, bp ; X*8
mov cx,8
mul cx
add ax, si ; X*8 +Y
add ax, di ; tab0 + X*8+Y
mov dl, ax; here is error, here I set the colour
pop dx
So I don't know how to fix it :( I have try different possibilities and northing work.

mov di, T34
mov si, 8
;------------------------------------
P1: mov bp, 8
;----------------
P2: cmp BYTE[di], 1
jnz short NOHIT
; save used REGISTER
; load register with the X,Y position and color
call putpixel
; get back the saved Register
NOHIT: ; increase the x position
inc di ; increase offset address of array
dec bp ; decrease counter and set zeroflag if register is zero
jnz P2 ; jump if zeroflag is not set
;-------------
; increase the y position + substract 8 from x position
dec si
jnz P1
;------------------------------------
It is also possible to start the counters for the loops with 0 for to increase the counter, but then we need a compare instruction for to leave the loop, if we want to run the loop from 0 to 8. The offset addresses inside of the array are pointed independent with no relationship to the counters.
With a little modifying (put an additional jump instruction in the code and a second call) it is also possible to set a black pixel if the byte of the array is 0. But i think this simple form of a nested loop is easier to understand in the first time.
Edit: Now it is compatible for NASM.
Edit2: Maybe it is more simple to store the x,y coordinates into a known ram location for modifying and reloading inside of a loop, if many parameters are in use.
Our ram location:
Color DB ? ; define byte
X_Pos DW ? ; define word
Y_Pos DW ?
Examples for to show how to access a memory location (default segment is DS):
mov [X_Pos], ax
mov [X_Pos], bx
mov [Color], dl
mov ax, [X_Pos]
mov bx, [Y_Pos]
mov dl, [Color]
mov WORD[X_Pos], 10
inc WORD[X_Pos]
sub WORD[X_Pos], 8
mov BYTE[Color], 4
inc BYTE[Color]
Edit3:
mov dl, ax; here is error, here I set the colour
It is not possible to mix an 8 bit register with a 16 Bit register.
Note:
AX = AL+AH
DX = DL+DH
Existing instruction are:
mov dl, al
mov dl, ah
mov dx, ax
movzx dl, ax

Related

Sorting an array in assembly 8086 16 bit

I am trying to sort an array by using functions that finds the smallest number in an array, and the other swaps two variables. But for some reason the array doesn't change and stays the same.
I thing I have a problem with the stack but I can't find it.
This is my code: sorry its long and not organized. I just started assembly.
`
org 100h
jmp start
array db 1,9,3,6,3 **;should get 1,2,3,6,9**
min_in_array dw ?
start:
lea si, array
push 5
push si
call sortArray
pop bx
pop bx
mov ah, 0
int 16h
ret
;doesn't work
PROC sortArray
push bp
mov bp, sp
mov dx, 0 ;the index
mov cx, [bp+6];size
mov di, [bp+4];array
loop_arr:
add di, dx
push di
call findMin
pop di
sub di, dx
add di, min_in_array
push dx
push di
call swap
pop di
pop dx
sub di, min_in_array
inc dx
mov ax, [di]
loop loop_arr
mov sp, bp
pop bp
ret
ENDP sortArray
;works
PROC findMin
push bp
mov bp, sp
sub sp, 4
mov cx, 0 ;init the counter
mov di, [bp+4]
mov al, [bp-2] ;initialising the min save var
mov al, [di]
mov bx, [bp-4] ;the index to save
mov bx, 0
run:
cmp al, [di]
ja change_min
cmp cx, 4 ;check if cx is lower than the size of the array
inc cx ;+1
inc di ;move forward in the array
jb run ;check again
jmp fin ;finished - cx = size
change_min:
mov al, [di] ;change the min
mov bx, cx ;assign the index
inc di
cmp cx, 4
je fin
inc cx
jmp run
fin:
mov sp, bp
pop bp
mov cx, 0
mov min_in_array, bx
ret
ENDP findMin
;function works
PROC swap
;creates fram
push bp
mov bp,sp
sub sp,2 ;make space for local temp
mov bx, [bp+6]
mov cx, [bp+4]
;swaping using the temp varaiable
mov [bp-2], bx
mov bx, cx
mov cx, [bp-2]
;close frame
mov sp, bp
pop bp
ret
ENDP swap
`
I have a problem with the stack but I can't find it.
Your use of the stack is actually fine: prologue, epilogue, cleaning.
But there's one additional thing that the stack is good at, and that's preserving register values. Your sortArray procedure depends on the CX register, but you destroy its value in the findMin and swap procedures!
You say findMin works, but I assure you it doesn't. Other than not preserving CX and containing a lot of unused code, findMin always processes 5 elements eventhough the supplied address moved up with each invokation, meaning you are processing garbage that follows the original array in memory. Moreover the result that you store in the min_in_array variable is an offset in the unsorted partition of the array, but after returning, sortArray will use this same value as an offset in the original array. Can't work that way...
You say swap works, but I assure you it doesn't. What you supply to this procedure is an offset in the original array and an (wrongly calculated) address within the original array. You fetch these arguments from the stack and only swap these in registers, nothing more. You never read/write in the array, so there's no swapping taking place.
See if next code points you in the right direction:
add di, dx
push cx ; Number of elements in the unsorted partition
push di ; Address of the start of the unsorted partition
call findMin ; -> AX (BL CX SI)
pop di
pop cx
push ax ; Address of the Min from the unsorted partition
push di ; Address of the start of the unsorted partition
call swap
...
; IN () OUT (ax) MOD (bl,cx,si)
PROC findMin
push bp
mov bp, sp
mov cx, [bp + 6]
mov si, [bp + 4]
min:
mov bl, [si]
mov ax, si
run:
dec cx
jz done
inc si
cmp bl, [si]
jb run
jmp min ; Go change min
done:
pop bp
ret
ENDP findMin

(Assembly Language) I'm trying to get a string to move across the screen 5 times before stopping

As the title states, I'm using assembly language to try to get a text to move left to right 5 times. I've pasted my code below. As of right now, what happens is it moves left to right 4 and a half times, starts over at the very left and it repeats infinity times. I feel like the error lies on where I placed my pop cx. I hope that maybe someone else can see the mistake and I just missed it.
.model small
.stack
.data
strg db 'Test$'
row db 12
col db 0
.code
main proc
mov ax,#data
mov ds,ax
dem: mov cx,5
push cx
mov cx,79
again: push cx ;clears the terminal
mov ah,6
mov al,0
mov bh,7
mov ch,0
mov cl,0
mov dh,24
mov dl,79
int 10h
mov ah,2
mov bh,0
mov dh,row ;row
mov dl,col ;col
int 10h
mov ah,9
mov dx, offset strg ;prints the text
int 21h
inc col
mov cx,1 ;x and y adds delay
y: push cx
mov cx,0ffffh
x: loop x
pop cx
loop y
pop cx
loop again
pop cx
loop dem
mov ah,4ch
int 21h
main endp
end main
what happens is it moves left to right 4 and a half times, starts over at the very left and it repeats infinity times.
I don't see where you get that '4 and a half times'. The infinite behaviour starts right away.
dem: mov cx,5
push cx
Your outer loop should initialize its counter outside of the loop.
mov cx,5
dem: push cx
I feel like the error lies on where I placed my pop cx.
Because your program uses the CX register for a lot of things, it is easy to loose track. Consider using a system that numbers what you push/pop on the stack:
mov cx,5
dem:
push cx ; (1) Outer loop
mov cx,79
again:
push cx ; (2) Inner loop
mov ah,6
mov al,0
mov bh,7
mov ch,0
mov cl,0
mov dh,24
mov dl,79
int 10h
mov ah,2
mov bh,0
mov dh,row
mov dl,col
int 10h
mov ah,9
mov dx, offset strg
int 21h
inc col
mov cx,1
y: push cx ; (3) Waiting loop
mov cx,0ffffh
x: loop x
pop cx ; (3)
loop y
pop cx ; (2)
loop again
pop cx ; (1)
loop dem
You don't always need to use CX. There are more registers at your disposal:
mov bp,1
y: mov cx,0ffffh
x: loop x
dec bp
jnz y

How to preserve an array or string in x86

I'm programming the game "15 puzzle game" in x86 using tasm asm/dosbox. I want to "save" or "preserve" my array called 'a' that is being declared in my data segment, so that after I swap the bytes around using upArrow, downArrow, etc... and then I press 'n' for new game, I can set my array 'a' back to it's original state as it was declared in my data segment. Here is my code:
.MODEL TINY
.386
.DATA
PROMPT DB "Enter q to quit, arrow keys to move, n to restart (new game) HAPPY HOLIDAYS!! :)$"
;this is board preset A
a DB 201,205,205,205,205,203,205,205,205,205,203,205,205,205,205,203,205,205,205,205,203,205,205,205,205,203,205,205,205,205,187,
DB 186,255,48,50,255,186,255,48,49,255,186,255,48,51,255,186,255,48,52,255,186,255,48,53,255,186,255,48,54,255,186,
DB 204,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,185,
DB 186,255,48,55,255,186,255,48,56,255,186,255,48,57,255,186,255,49,48,255,186,255,49,49,255,186,255,49,50,255,186,
DB 204,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,185,
DB 186,255,49,51,255,186,255,49,52,255,186,255,49,53,255,186,255,49,54,255,186,255,49,55,255,186,255,255,255,255,186,
DB 204,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,206,205,205,205,205,185,
DB 186,255,49,56,255,186,255,49,57,255,186,255,50,48,255,186,255,50,49,255,186,255,50,50,255,186,255,50,51,255,186,
DB 200,205,205,205,205,202,205,205,205,205,202,205,205,205,205,202,205,205,205,205,202,205,205,205,205,202,205,205,205,205,188,"$"
col DB 0
row DB 0
board DB 0
.CODE
org 100h
MAIN PROC
;initialize display step 0
MOV AH, 00h
MOV AL, 03h
INT 10h
MOV AX, 0B800h
MOV ES, AX
XOR di,di
;initialize configuration and dislay prompt step 1
newGame:
call initConfig
;display board step 2
;wait for key step 3
game:
;print board
call printBoard1
;get cursor x y
call SetCursor
MOV AH, 0
INT 16H
MOV BL, AL
;up arrow
CMP AH, 48h
jz upArrow
;down arrow
CMP AH, 50h
jz downArrow
;right arrow
CMP AH, 4dh
jz rightArrow
;left arrow
CMP AH, 4bh
jz leftArrow
;lowercase q
CMP AL, 71h
jz EXIT
;uppercase q
CMP AL, 51h
jz EXIT
;lowercase n
CMP AL, 6eh
jz newGame
;uppercase n
CMP AL, 4eh
jz newGame
jmp game
MAIN ENDP
EXIT:
MOV AH, 4CH ; return control to DOS
INT 21H
SetCursor:
mov dl, col
mov dh, row
mov bh, 0
mov ah, 02h
int 10h
ret
getStrlen:
lodsb
cmp al, 24h
je strlen_end
inc bx
jmp getStrlen
strlen_end:
ret
loadAndDisplayStr:
lodsb
stosw
dec cx
jne loadAndDisplayStr
ret
printBoard1:
MOV board, 1
xor dx,dx
xor ax,ax
mov cx, 9
myloop1:
push cx
lea si, a
add si, dx
mov cx, 31
mov di, ax
push ax
mov ah, 4
call loadAndDisplayStr
pop ax
add ax, 160
add dx, 32
pop cx
dec cx
jnz myloop1
ret
upArrow:
xor si, si
xor di, di
lea bx, a
mov ax, 32
sub row, 2
mul row
add al, col
mov di, ax
mov ax, 32
add row, 2
mul row
add al, col
mov si, ax
mov dx, [bx+si]
xchg dx, [bx+di]
xchg [bx+si], dx
sub row, 2
jmp game
downArrow:
xor si, si
xor di, di
lea bx, a
mov ax, 32
add row, 2
mul row
add al, col
mov di, ax
mov ax, 32
sub row, 2
mul row
add al, col
mov si, ax
mov dx, [bx+si]
xchg dx, [bx+di]
xchg [bx+si], dx
add row, 2
jmp game
leftArrow:
xor si, si
xor di, di
lea bx, a
mov ax, 32
sub col, 5
mul row
add al, col
mov di, ax
mov ax, 32
add col, 5
mul row
add al, col
mov si, ax
mov dx, [bx+si]
xchg dx, [bx+di]
xchg [bx+si], dx
sub col, 5
jmp game
rightArrow:
xor si, si
xor di, di
lea bx, a
mov ax, 32
add col, 5
mul row
add al, col
mov di, ax
mov ax, 32
sub col, 5
mul row
add al, col
mov si, ax
mov dx, [bx+si]
xchg dx, [bx+di]
xchg [bx+si], dx
add col, 5
jmp game
initConfig:
;put the cursor at 00
mov col, 27
mov row, 5
;gets strlen of prompt and stores it in BX
lea si, PROMPT
xor bx, bx
call getStrlen
;display prompt
lea si, PROMPT
mov cx, bx
mov ah, 2
mov di, 5a0h
call loadAndDisplayStr
ret
END MAIN
The way I see it is there are 2 ways of doing this. One way would be to create an empty array, and every time the user makes a move (up/down/left/right) I can push this to a stack, and then when the user hits 'n' for new game, I just pop through that stack and reverse all the moves.
Another alternative would be to create 2 identical boards (arrays/string) 'a' and 'b', and then the user would manipulate board 'a' till they decide to hit 'n' for a new game, and then I would some how set 'a' = 'b'
There's no magic way, you just have to copy the array like you would in C.
I'd suggest having one master copy of the data that you keep clean / untouched, never ever writing into it.
Allocate uninitialized space for the working game state somewhere, e.g. on the stack or in the BSS1.
At the start of every game (including the first one), copy the preset whole array to the scratch space for the current game. (e.g. with rep movsb or rep movsw after setting CX, SI, and DI. ES and DS segment regs are already equal segment because of .model tiny. i.e. implement a memcpy however you like.)
So you don't need to write the initializer data twice or anything like that, and only one copy of it needs to be in the file.
And no you don't need any exchanging, just a block copy. Get the assembler to calculate the size of the whole thing by putting a label at the end, or put datasize = $ - a right after the end of a to get the size in bytes.
Footnote 1: See #MichaelPetch's comment for details on how to declare a label in the .data? segment so you can use normal label/symbol syntax. Like gamestate datasize dup(?), where datasize is an = or equ constant you got the assembler to calculate earlier from the size of the preset.
I think .data? is just space past the end of where DOS loads your .com file, and you can use space from there out to near the end of a 64k segment where the program-loader put your stack. (Unlike the .bss under a modern OS is not zeroed to start with. That's fine for this, you want to write the space you use before you read/modify it anyway.)
#DavidWohlferd also suggests you could re-read part of the executable from disk, with DOS file open/read system calls. That could be the start of a save-game mechanism. In its simplest form, if the first n bytes of your program are all read-only (code and constant data) apart from this game-state array, you could read the first n bytes of the raw .com file into memory at ds:100h (or cs or es, it's all the same in a tiny memory model). Overwriting instructions with themselves (like a jmp rel16 over the data) is fine.

Assembly graphic couldn't display right colour from array

Welcome.
I could't get values from 2d array. I am trying and trying and it doesn't work. I use NASM 16 DOS
I want to have blue letter E on red backgroung. I only get square random colours.
'1' in array is blue,'4' is red. It could be spinned, but it doesn't matter.
I have no idea what is wrong. I'm trying to do this a couple od days.
Here is my code:
segment .data
segment .code
..start:
mov ax, 13h
int 10h ; switch to 320x200 mode
mov ax, 0a000h ; The offset to video memory
mov es, ax ; We load it to ES through AX,
; because immediate operation
; is not allowed on ES
;;;;;;;;;;;;;;;;;;;;;;
mov si, T34 ; my array
mov word [Y_Start], 10 ; Y start line count values in register
mov word [X_Start], 20 ; X start line
mov word [Y], 10 ; Y start line
mov word [X], 20 ; X start line
mov dx, 4 ; colour (red)
mov cx, 8 ; loop top counter
top:
add word [Y], 1
push cx ;loop top counter =
mov cx, 8 ;inside loop counter
inside:
add word [X], 1
;////////////////////////////////////////////// count colour
push ax ; remember value before procedure
push bx
push cx
push dx
mov ax, word [X]
mov cx,8
mul cx ;X*8
add ax, word[Y] ; X*8 +Y
mov cx,4
mul cx ; (X*8+Y)*4
add ax, si ; tab0 + (X*8+Y)*4
pop dx
mov dx, ax; colour
pop cx
pop bx
pop ax
;///////////////////////////////////////////
mov ax, word [Y]
mov bx, word [X]
push ax ; remember value before procedure
push bx
push cx
call putpixel
pop cx ; go back to old values
pop bx
pop ax
loop inside
mov bx, word [X_Start] ; move to X start
mov word [X], bx ;
pop cx ;loop top counter
loop top
;;;;;;;;;;;;;;;;;;;;;;;;;
xor ah, ah
int 16h ; keyboard (wait for key)
mov ax, 3
int 10h ; go to text mode
mov ax, 4c00h
int 21h ; return to DOS, exit code 0
;;;;;;;;;;;;;;;;;;;;;
putpixel:
push dx ; mul changes dx too
mov cx, 320
mul cx ; multiply Y (ax) by 320 (one row)
add ax, bx ; and add X (bx) (result= dx:ax)
mov di, ax
pop dx
mov [es:di], dx ; store color/pixel
ret
;;;;;;;;;;;;;;;;;;;;;;
X_Start DW 0 ; start letter position
Y_Start DW 0
X DW 0 ;current letter position
Y DW 0
T34 DB 1,1,1,1,1,1,1,1
DB 1,4,4,4,4,4,4,4
DB 1,4,4,4,4,4,4,4
DB 1,4,4,4,4,4,4,4
DB 1,1,1,1,1,1,1,1
DB 1,4,4,4,4,4,4,4
DB 1,4,4,4,4,4,4,4
DB 1,1,1,1,1,1,1,1
I didn't catch your approach, but I can show you how I would do it:
segment .code
..start:
mov ax, data ; Initialize DS (needed for .exe-program)
mov ds, ax
mov ax, 0A000h ; Segment to video memory
mov es, ax
mov ax, 13h
int 10h ; Switch to 320x200 mode
mov si, T34 ; DS:SI = letter
mov bx, [X_Start]
mov ax, [Y_Start]
call vector_to_memory
mov di, ax ; ES:DI = video memory
call paint
; once more
add word [X_Start], 8 ; That's one small step for a man
mov si, T34 ; DS:SI = letter
mov bx, [X_Start]
mov ax, [Y_Start]
call vector_to_memory
mov di, ax ; ES:DI = video memory
call paint
xor ah, ah
int 16h ; keyboard (wait for key)
mov ax, 3
int 10h ; go to text mode
mov ax, 4c00h
int 21h ; return to DOS, exit code 0
paint: ; Args: DS:SI = letter, ES:DI: video memory
mov ax, 8
.l1:
mov cx, 8 ; repetition count for REP
rep movsb ; CX times (one row): [DS:SI] => [ES:DI], SI++, DI++
add di, (320-8) ; next row
sub ax, 1 ; no row left?
jnz .l1 ; no: once more
ret ; yes: paint is done, return
vector_to_memory: ; Args: BX = X, AX = Y
push dx ; mul changes dx too
mov cx, 320 ; video mode width
mul cx ; DX:AX = AX * CX
add ax, bx ; left indentation
pop dx
ret ; Return: AX = offset in memory
segment .data
T34:
DB 1,1,1,1,1,1,1,1
DB 1,4,4,4,4,4,4,4
DB 1,4,4,4,4,4,4,4
DB 1,4,4,4,4,4,4,4
DB 1,1,1,1,1,1,1,1
DB 1,4,4,4,4,4,4,4
DB 1,4,4,4,4,4,4,4
DB 1,1,1,1,1,1,1,1
X_Start DW 10 ; start letter position
Y_Start DW 20
segment stack stack
resb 0x1000
HTH
You're not loading the pixel values correctly:
add ax, si ; tab0 + (X*8+Y)*4
mov dx, ax; colour <-- Here you're just copying the _address_, you're
not loading the value stored at that address.
Those two instructions should be changed to:
add si,ax
mov dl,[si]
Note the use of dl since you're dealing with bytes. I also switched the add around because [ax] wouldn't be a valid effective address. This means that you'll have to reload si with the address of the array on every iteration of the loop.
The line mov [es:di], dx in putpixel should also be changed to mov [es:di], dl.
Some of your multiplications could be simplified: to multiply a register by 4 you can do shl reg,2, and to multiply by 8 you can do shl reg,3.

Assembly x86 Delay loop

hi i made program that will rotate two symbols - \ and / but i dont know how to set cx counter in nested loops can someone give me advice or help me ?
here is the code of that part
program:
mov ah, 0fh ; function - get video mode
int 10h
push ax ; save number of columns
push bx ; save page number
mov ah, 0 ; function - set video mode
int 10h
mov al, 0003h ;set video mode
int 10h
mov cx,10d ; Outer loop counter how many symbols rotate
mov bx,50d ; this is for delay loop
OuterLoop:
push cx
mov ah,02h
mov bh, 0 ;cursor set
mov dh, 2
mov dl, 10
int 10h
mov AH,0Ah
mov al,"/" symbol /
mov bh,0
mov cx,1
int 10h
mov cx,bx
call Delay ;delay loop
sub bx,15d
mov ah,02h
mov bh, 0
mov dh, 2 cursor set
mov dl, 10
int 10h
mov AH,0Ah
mov al,"\" ;symbol \
mov bh,0
mov cx,1
int 10h
mov cx,bx
call Delay ; another delay
sub bx,10
pop cx ; Restore current CX
loop OuterLoop
jmp START ; and after end it should jump to start where is menu with choices
it should work like this
write /
delay for example 10 sec
write \
delay 8 sec
and jump to beginning and loop
thanks for advices
this is my delay procedure
Delay PROC NEAR ;
push ds ;
push si ;
push ax ;
xor ax, ax ;AX = 0
mov ds, ax ;DS = 0
mov si, 046Ch ;
t1: mov ax, [si] ;
t2: cmp ax, [si] ;
je t2 ;
loop t1 ;
pop ax ;
pop si ;
pop ds ;
ret ;
Delay ENDP ;
i am still working on this app but it is not working all i need is this steps to be made
program : start of loop
\
delay delay 100 times
/
delay delay 80 times
loop
and after every loop to decrease delay like this 100 times 80,60,40 and so on but i dont know where to put push and pop cx because my delay procedure is working with cx. i just set cx for example to 100 and it makes delay and so on.
I see two problems:
First, bx is initialized here
mov bx,50d ; this is for delay loop
but then it gets over-written by
mov bh, 0
bh is bits 15:8 of bx
Second, in the Delay procedure, what modifies the location at [si] so that the je t2 branch falls thru? As it stands that is an infinite loop:
xor ax, ax ;AX = 0
mov ds, ax ;DS = 0
mov si, 046Ch ;
t1: mov ax, [si] ;
t2: cmp ax, [si] ;
je t2 ;
loop t1 ;
Update:
I found that address 0x46c is a BIOS address that contains time information.
http://www.osdata.com/system/physical/lowmem.htm
So the memory you are watching in that loop is a location updated by BIOS with a counter of timer ticks (counts every 54.9 milliseconds), see
http://code.google.com/p/xtideuniversalbios/source/browse/trunk/Assembly_Library/Src/Time/TimerTicks.asm?spec=svn131&r=131
So to answer your question, before calling your Delay procedure you should load CX with the count of BIOS ticks you wish to delay (time in milliseconds divided by 54.9).
For to drawing my own cursor i use the timer interrupt for to become a more steady delay on different performant CPUs.
Cursor_Speed = 7
;-------------DATA--------------------------------------
CURFLAG DB 0, 0, 0, 0
ALTVEC DD 0
;-------------CODE--------------------------------------
cli
xor ax, ax
mov es, ax
mov ebx, DWORD PTR es:[8*4] ; Get the old Vector (Offset/Segment)
mov DWORD PTR[ALTVEC], ebx ; save it
mov cs:DWORD PTR[OLDVEC], ebx
mov es:[8*4], OFFSET NEWVEC ; Set the new IRQ-Vector
mov es:[(8*4)+2], cs
mov al, 36h ; Set 18,2 Hertz(Standard)
out 43h, al
xor al, al
out 40h, al ; low
out 40h, al ; high
sti
;---------------------------------------------------
......
;---------------------------------------------------
NEWVEC: inc BYTE PTR[CURFLAG+1]
cmp BYTE PTR[CURFLAG+1], Cursor_Speed
jb short NOHIT
mov BYTE PTR[CURFLAG+1], 0
xor BYTE PTR[CURFLAG], 1
NOHIT: DB 0EAh ; jmp far
OLDVEC DD 0
;---------------------------------------------------
....
Alternativly we can wait of the vsinc with polling port 3DAh for to become a little bit lesser precice delay.
Dirk

Resources