[b][red]This message was edited by shaolin007 at 2003-10-29 12:21:28[/red][/b][hr]
I'm still learning assembly and I'm trying to practice the stos instruction. First off here is my code...
[code]
BITS 16
ORG 0x0100
SEGMENT .text ;Main code segment
mov ax, 0b800h
mov es, ax
xor ax,ax
xor di,di
mov cx, 3999
call machine_gun
mov ah, 08h
int 21h
call done
machine_gun:
mov al, 'a'
mov [es:di], al
dec cx
inc di
rep stosb
ret
done:
mov ax, 4c00h
int 21h
ret
[/code]
1st question is, could I use the stosw instruction to do this and how? All I could do with it was write an 'a' then the rest of the screen was yellow. When I use the stosb instruction it works out fine. 2nd, I thought the default background attribute would be black, but it's yellow, how do you change that directly? 3rd, why do I have to double the cx counter since 80x25=2000? Thanks for your help.
Comments
so you use something like that:
mov al,'A'
mov al,07h
stosw ; stos a grey-'A' on black ground
A simple version
[code]
BITS 16
ORG 0x0100 ;Nasm .COM file
mov ax,0b800h
mov es,ax ;FAST CLEAR SCREEN CODE
xor di,di ;ES:DI = destination
MOV AH,7 ;color dim white on black, 8=grey
MOV AL,32 ;32=space character
mov cx,2000 ;count
REPZ STOSW ;quick do the work
mov ah,08h ;pause, get key with out echo
int 21h
mov ax,4c00h ;correct exit code
int 21h
[/code]
Your code I commented/butchered
[code]
BITS 16
ORG 0x0100 ;this looks NASMish, so the next .COM line isn't needed
; SEGMENT .text ;Main code segment
mov ax,0b800h
mov es,ax
xor ax,ax ;char 0 looks like a space,
;& attribute 0 is black on black
;so you can never write anything on the screen you can see
;except for the last byte cause you used 3999 instead of 4000?
xor di,di
mov cx,3999 ;4000 is what I use
call machine_gun ;if your code only calls a proc once, put it
;where it's called, but just a REPZ STOSW is all that's required
mov ah, 08h
int 21h
call done ; should be JMP DONE, CALL pushes the return address
JMP DONE
machine_gun:
mov al, 'a' ;you don't have AH=color
mov BYTE [es:di], al ;BYTE size was not stated, (it worked though?)
dec cx ;now CX=3998 two bytes short of a full screen
inc di ; I don't know why you DEC DI,
; INC DI ; would be proper code in a loop;
rep stosb ; you are writing the character to the attribute byte also
;I don't know why the mov BYTE then the stosb, just testing stuff I guess?
ret
:
DONE:
mov ax, 4c00h ;correct exit code
int 21h
; ret ;this never gets run, IP never gets here.
;A .COM will quit with a RET statement but your AX=4c00h INT 21h
;is the correct exit/quit program code.
[/code]
:
: 1st question is, could I use the stosw instruction to do this and how?
REPZ STOSW ; AH=color, AL=character, CX=2000 count
: All I could do with it was write an 'a' then the rest of the screen was yellow.
You wrote the character to the attribute byte also
: When I use the stosb instruction it works out fine.
Use REPZ STOSW or in a loop STOSB & INC DI to skip the attribute byte
: I thought the default background attribute would be black, but it's yellow, how do you change that directly?
stos Word would have done that, but black writeing on a black back ground can't be seen.
: Why do I have to double the cx counter since 80x25=2000?
2000 characters
+2000 attributes
=4000 bytes total
but if you write two bytes at a time AH=color AL=char REPZ STOSW then CX=2000
REPZ = REPeat untill cx = Zero
I hope that helps some how
Bitdog
[code]
BITS 16 ;Set code generation to 16 bit mode
ORG 0x0100 ;Set code start address to 0100h
mov ax, 0b800h
mov es, ax
xor ax,ax
xor di,di
mov cx, 2000
mov al, 'a'
mov ah, 07h
mov [es:di], ax
dec cx
inc di
inc di
repz stosw
mov ah, 08h
int 21h
mov ax, 4c00h
int 21h
[/code]
Have a good weekend!
:take a look again, and see if I can improve it further.
[code]
BITS 16 ;Set code generation to 16 bit mode
ORG 0x0100 ;Set code start address to 0100h
mov ax, 0b800h
mov es, ax
; xor ax,ax ;not needed
xor di,di
mov cx, 2000
mov al, 'a'
mov ah, 07h
; mov [es:di], ax ;not needed loop part
; dec cx
; inc di
; inc di
repz stosw ;this does all the work for you
mov ah, 08h
int 21h
mov ax, 4c00h
int 21h
[/code]
The un_needed part is for a loop, but the REPZ STOSW is a loop proc in an instruction that's as quick as anything.
You're writing an 'a' 2000 times which seems funny, but it's a test program I take it. Changeing the 'a' to 32=space=' ' would clear the screen and thats usefull code.
If you wanted to do the loop thing, here's a couple stuffs
[code]
;ES:DI assume is already pointed to the Vmem destination
MOV CX,2000 ;loop counter
MOV AL,' ' ;character=space 32
MOV AH,7 ;color, 4=red
ZZTOP:
MOV WORD [ES:DI],AX ; stow the char & attribute=color
INC DI
INC DI
DEC CX ;this sets the ZF=Zero Flag when CX=0
JNZ ZZTOP ;jump short if CX not equil 0
;or if you want to write a string, try this,
MESSAGE DB "Howdy Wurld !",0
;ES:DI destination already = Vseg:offset
; MOV CX,2000 ;(edited OOPS, CX isn't needed)
MOV AH,4 ;color
MOV SI,MESSAGE ; address of message source in DS:SI now
ZZTOP:
LODSB ;=get a message byte in AL from [DS:SI] & INC SI
OR AL,AL ;check for 0=nul string end
JZ DONE
STOSW ;write both the AL=char & AH=color
JMP SHORT ZZTOP
DONE:
[/code]
PS, your codeing looked real clean, congrats.........
Bitdog