I'm working on a lab project, and I ran into a little problem. I already have written some code to make musical notes play, that part seems to work. The problem I'm having is that I handle the 'm' key for my music, and when I press it, the music plays, as it should. However, I need to handle another key or button to PAUSE the music and when it is pressed again, (a second time) the music should continue to play, right where it left off. I really cannot figure out how to handle the second key press, so the music will be continued, and not started over again. I am working in GUI Turbo Assembler, and this is the core of the code I have so far:
TITLE MUSIC.EXE
STACKSG SEGMENT PARA STACK 'Stack'
DW 128 DUP(?)
STACKSG ENDS
DATASG SEGMENT PARA 'Data'
DATASG ENDS
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG, DS:DATASG, SS:STACKSG, ES:NOTHING
SOUND PROC
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
MOV AL, 0B6H
OUT 43H, AL
MOV DX, 14H
MOV AX, 4F38H
DIV DI
OUT 42H, AL
MOV AL, AH
OUT 42H, AL
IN AL, 61H
MOV AH, AL
OR AL, 3
OUT 61H, AL
L1: MOV CX, 6801
L2: LOOP L2
DEC BX
JNZ L1
MOV AL, AH
OUT 61H, AL
POP DI
POP DX
POP CX
POP BX
POP AX
RET
SOUND ENDP
MAIN PROC
MOV BX, 50
L3: MOV AH, 0
INT 16H
CMP AL, 'x'
JE EXIT
CMP AL, 'q'
JE DO
CMP AL, 'w'
JE RE
CMP AL, 'e'
JE MI
CMP AL, 'r'
JE FA
CMP AL, 't'
JE SOL
CMP AL, 'y'
JE LA
CMP AL, 'u'
JE CI
CMP AL, 'm'
JE MEL
JNZ L3
DO: MOV DI, 131
CALL SOUND
JMP L3
RE: MOV DI, 147
CALL SOUND
JMP L3
MI: MOV DI, 165
CALL SOUND
JMP L3
FA: MOV DI, 175
CALL SOUND
JMP L3
SOL: MOV DI, 196
CALL SOUND
JMP L3
LA: MOV DI, 220
CALL SOUND
JMP L3
CI: MOV DI, 247
CALL SOUND
JMP L3
EXIT: MOV AH, 00H
MOV AL, 03H
INT 10H
MOV AX, 4C00H
INT 21H
RET
MEL:
L4: LOOP L4
MOV DI, 147
CALL SOUND
MOV DI, 147
CALL SOUND
MOV DI, 147
CALL SOUND
MOV DI, 196
CALL SOUND
MOV DI, 196
CALL SOUND
MOV DI, 175
CALL SOUND
MOV DI, 165
CALL SOUND
MOV DI, 220
CALL SOUND
MOV DI, 220
CALL SOUND
MOV DI, 196
CALL SOUND
MOV DI, 147
CALL SOUND
MOV DI, 147
CALL SOUND
MOV DI, 147
CALL SOUND
MOV DI, 147
CALL SOUND
JMP L4
MAIN ENDP
CODESG ENDS
END MAIN
Happy New Year #everybody!
; Name: music.asm
; Assemble: tasm.exe music.asm
; Link: tlink.exe music.obj
; Run in DOSBox: music.exe
a0 = 43388 ; 27.5000 hz
ais0 = 40953 ; 29.1353 hz
h0 = 38655 ; 30.8677 hz
c1 = 36485 ; 32.7032 hz
cis1 = 34437 ; 34.6479 hz
d1 = 32505 ; 36.7081 hz
dis1 = 30680 ; 38.8909 hz
e1 = 28958 ; 41.2035 hz
f1 = 27333 ; 43.6536 hz
fis1 = 25799 ; 46.2493 hz
g1 = 24351 ; 48.9995 hz
gis1 = 22984 ; 51.9130 hz
a1 = 21694 ; 55.0000 hz
ais1 = 20477 ; 58.2705 hz
h1 = 19327 ; 61.7354 hz
c2 = 18243 ; 65.4064 hz
cis2 = 17219 ; 69.2957 hz
d2 = 16252 ; 73.4162 hz
dis2 = 15340 ; 77.7817 hz
e2 = 14479 ; 82.4069 hz
f2 = 13666 ; 87.3071 hz
fis2 = 12899 ; 92.4986 hz
g2 = 12175 ; 97.9989 hz
gis2 = 11492 ; 103.8260 hz
a2 = 10847 ; 110.0000 hz
ais2 = 10238 ; 116.5410 hz
h2 = 9664 ; 123.4710 hz
c3 = 9121 ; 130.8130 hz
cis3 = 8609 ; 138.5910 hz
d3 = 8126 ; 146.8320 hz
dis3 = 7670 ; 155.5630 hz
e3 = 7240 ; 164.8140 hz
f3 = 6833 ; 174.6140 hz
fis3 = 6450 ; 184.9970 hz
g3 = 6088 ; 195.9980 hz
gis3 = 5746 ; 207.6520 hz
a3 = 5424 ; 220.0000 hz
ais3 = 5119 ; 233.0820 hz
h3 = 4832 ; 246.9420 hz
c4 = 4561 ; 261.6260 hz
cis4 = 4305 ; 277.1830 hz
d4 = 4063 ; 293.6650 hz
dis4 = 3835 ; 311.1270 hz
e4 = 3620 ; 329.6280 hz
f4 = 3417 ; 349.2280 hz
fis4 = 3225 ; 369.9940 hz
g4 = 3044 ; 391.9950 hz
gis4 = 2873 ; 415.3050 hz
a4 = 2712 ; 440.0000 hz
ais4 = 2560 ; 466.1640 hz
h4 = 2416 ; 493.8830 hz
c5 = 2280 ; 523.2510 hz
cis5 = 2152 ; 554.3650 hz
d5 = 2032 ; 587.3300 hz
dis5 = 1918 ; 622.2540 hz
e5 = 1810 ; 659.2550 hz
f5 = 1708 ; 698.4560 hz
fis5 = 1612 ; 739.9890 hz
g5 = 1522 ; 783.9910 hz
gis5 = 1437 ; 830.6090 hz
a5 = 1356 ; 880.0000 hz
ais5 = 1280 ; 932.3280 hz
h5 = 1208 ; 987.7670 hz
c6 = 1140 ; 1046.5000 hz
cis6 = 1076 ; 1108.7300 hz
d6 = 1016 ; 1174.6600 hz
dis6 = 959 ; 1244.5100 hz
e6 = 905 ; 1318.5100 hz
f6 = 854 ; 1396.9100 hz
fis6 = 806 ; 1479.9800 hz
g6 = 761 ; 1567.9800 hz
gis6 = 718 ; 1661.2200 hz
a6 = 678 ; 1760.0000 hz
ais6 = 640 ; 1864.6600 hz
h6 = 604 ; 1975.5300 hz
c7 = 570 ; 2093.0000 hz
cis7 = 538 ; 2217.4600 hz
d7 = 508 ; 2349.3200 hz
dis7 = 479 ; 2489.0200 hz
e7 = 452 ; 2637.0200 hz
f7 = 427 ; 2793.8300 hz
fis7 = 403 ; 2959.9600 hz
g7 = 380 ; 3135.9600 hz
gis7 = 359 ; 3322.4400 hz
a7 = 339 ; 3520.0000 hz
ais7 = 320 ; 3729.3100 hz
h7 = 302 ; 3951.0700 hz
c8 = 285 ; 4186.0100 hz
whole_note = 1800
half_note_dot = whole_note/2 + whole_note/4
half_note = whole_note/2
quarter_note_dot = whole_note/4 + whole_note/8
quarter_note = whole_note/4
eighth_note = whole_note/8
pause = 30
LOCALS
.MODEL SMALL
.STACK
.DATA
div1 dd 14318180
div2 dd 786432000
AuldLangSyne dw 0,eighth_note
dw g3,quarter_note
dw c4,quarter_note_dot,h3,eighth_note,c4,quarter_note,e4,quarter_note
dw d4,quarter_note_dot,c4,eighth_note,d4,quarter_note,e4,eighth_note,d4,eighth_note
dw c4,quarter_note,0,pause,c4,quarter_note,e4,quarter_note,g4,quarter_note
dw a4,half_note_dot,0,pause,a4,quarter_note
dw g4,quarter_note_dot,e4,eighth_note,0,pause,e4,quarter_note,c4,quarter_note
dw d4,quarter_note_dot,c4,eighth_note,d4,quarter_note,e4,eighth_note,d4,eighth_note
dw c4,quarter_note_dot,a3,eighth_note,0,pause,a3,quarter_note,g3,quarter_note
dw c4,half_note_dot,0,quarter_note,a4,quarter_note
dw g4,quarter_note_dot,e4,eighth_note,0,pause,e4,quarter_note,c4,quarter_note
dw d4,quarter_note_dot,c4,eighth_note,d4,quarter_note,a4,quarter_note
dw g4,quarter_note_dot,e4,eighth_note,0,pause,e4,quarter_note,g4,quarter_note
dw a4,half_note_dot,0,pause,a4,quarter_note
dw g4,quarter_note_dot,e4,eighth_note,0,pause,e4,quarter_note,c4,quarter_note
dw d4,quarter_note_dot,c4,eighth_note,d4,quarter_note,e4,eighth_note,d4,eighth_note
dw c4,quarter_note_dot,a3,eighth_note,0,pause,a3,quarter_note,g3,quarter_note
dw c4,half_note_dot
dw 0,0
Welcome db "[p] Pause (any key for resuming) [r] Restart [x] Exit $"
.CODE
.486
delay PROC NEAR ms:word ; ARG on stack: delay in ms (granularity ~55 ms)
push bp
mov bp, sp
sub sp, 4
xor ax, ax
mov es, ax
mov edx, es:[046Ch]
; Ticks/sec: 14318180 / 12 / 65536 = 18.206785178403397675542331069912 -> 54.9254 mS
fild word ptr ms
fimul dword ptr div1
fidiv dword ptr div2
fistp dword ptr [bp-4]
add edx, [bp-4]
##L1:
mov eax, es:[046Ch]
cmp eax, edx
jb ##L1
leave
ret 2
delay ENDP
play PROC NEAR ; ARG si: pointer to freq/duration pairs, end with 0/0
mov di, si ; Preserve it for the check_key routine
##L1:
cmp word ptr [si], 0 ; No tone?
je ##J1 ; Yes: skip the sound blocks, just delay
; Set up frequency
cli ; Don't disturb the setting sequence
mov al, 0B6h
out 43h, al
mov ax, [si]
out 42h, al
mov al, ah
out 42h, al
sti
in al, 61h ; Speaker on
or al, 03h
out 61h, al
##J1:
push word ptr [si+2] ; Hold the tone for a certain while
call delay
in al, 61h ; Speaker off
and al, 0FCh
out 61h, al
add si, 4
call check_key ; DI: pointer for restart
cmp word ptr [si+2], 0
jne ##L1
ret
play ENDP
check_key PROC ; ARG di: pointer for restart
mov ah, 1 ; Check keyboard
int 16h
jz ##done ; No key -> return
mov ah, 0 ; Get key
int 16h
##K0: ; Pause
cmp al, 'p'
jne ##K1
call ##pause
##K1:
cmp al, 'P'
jne ##K2
##pause:
mov ah, 0
int 16h
push eighth_note
call delay
jmp ##K0
##K2: ; Exit
cmp al, 'x'
je ##exit
cmp al, 'X'
jne ##K3
##exit:
mov ax, 4C00h
int 21h
##K3: ; Restart
cmp al, 'r'
je ##restart
cmp al, 'R'
jne ##K4
##restart:
mov si, di
##K4: ; Placeholder for further key checks
##done:
ret
check_key ENDP
main PROC
mov ax, #data
mov ds, ax
mov ah, 9
lea dx, Welcome
int 21h
lea si, AuldLangSyne
call play
mov ax, 4C00h
int 21h
main ENDP
END main
The best place for such a thing is the loop L2:
...
L1: MOV CX, 6801
L2:
push ax ; Preserve AX
mov ah, 1 ; CHECK FOR KEYSTROKE
int 16h
jz done ; No keystroke, no pause
mov ah, 0 ; GET KEYSTROKE
int 16h
cmp al, 'p' ; Key == 'p'?
jnz done ; No -> no action
#J1: ; Loop for pause
pop ax ; POP/PUSH: Get AX and store it
push ax
mov al, ah ; Sound off
out 61h, al
mov ah, 0 ; GET KEYSTROKE (wait)
int 16h
cmp al, 'p' ; Key == 'p'?
jne #J1 ; No: continue with pause
OR AL, 3 ; Yes: sound on
OUT 61H, AL
done:
pop ax ; Restore AX
LOOP L2
DEC BX
JNZ L1
...
A keystroke on P (lower case) switches the pause on and off.
Related
I made a program that reads a string and converts it into a number. A string representation of the number entered in the decimal system. The result of of converting is in register ax.
I use tasm16.
How do I do that I can convert a string bigger(more than 65535)?
model small
stack 100h
printstring macro msg
mov ah,09h
mov dx,offset msg
int 21h
endm
data segment
cr equ 0dh
lf equ 0ah
errorInput db 'Wrong input',cr,lf,'$'
inputAmsg db 'Please input A',cr,lf,'$'
outstring db 'Output:',cr,lf,'$'
maxAbuf db 10
db ?
db 10 dup(0)
db '$'
result dw 0
data ends
code segment
assume cs:code, ds:data
start:
mov ax,data
mov ds,ax
;input A
printstring inputAmsg
mov ah,0ah
lea dx,maxAbuf
int 21h
printstring outstring
mov ah,09h
lea dx,maxAbuf+2
int 21h
;in:
;dx:address of string
;out
;dx:ax - result ;work only ax
;
call Convert
jmp exit
;in:
;dx:address of string
;out
;dx:ax - result
;9999989d = 989675h
Convert proc
xor ax,ax
xor cx,cx
mov bx,10 ;base
mov si, offset dx
xor dx,dx
getnewchar: mov cl,[si]
cmp cl,0dh ;if `$` exit
jz endproc
sub cl,'0' ;or 30h
mul bx
add ax,cx
;I do not know what to write here, if there is an exit for the bit grid.
adc dx,0
inc si
jmp getnewchar
endproc:
ret
endp
exit: mov ax,4c00h
int 21h
code ends
end start
You could, for example, extend your multiplication by 10 from 16 to 32 bits like this:
; file: mul32ten.asm
; compile: nasm.exe mul32ten.asm -f bin -o mul32ten.com
bits 16
org 0x100
xor dx, dx
xor ax, ax
mov si, MyStr
NextDigit:
mov bl, [si]
or bl, bl
je Done
call MulDxAxBy10
sub bl, '0'
add al, bl
adc ah, 0
adc dx, 0
inc si
jmp NextDigit
Done:
; dx:ax should be equal to 7FFFFFFF now
ret
MulDxAxBy10:
push si
push di
shld dx, ax, 1
shl ax, 1 ; dx:ax = n * 2
mov si, ax
mov di, dx ; di:si = n * 2
shld dx, ax, 2
shl ax, 2 ; dx:ax = n * 8
add ax, si
adc dx, di ; dx:ax = n * 8 + n * 2 = n * (8 + 2) = n * 10
pop di
pop si
ret
MyStr db "2147483647", 0
I am writing a bootloader in x86-16 assembly on a floppy disk, meaning that I will have to read from the disk in order to load more of my code, however, every time I attempt to read the disk and check the disk status code, I always get 0x04 - sector not found. I have attempted to read with CX set to 0x0000, 0x0001, and 0x0101, but I don't really know what to do, or what I am doing wrong.
INT 13,1 - Disk Status Codes
INT 13,2 - Read Disk Sectors
BITS 16
%include "C:\x86asm\nasm\nasm.asm"
;%macro pad 1-2 0
; times %1 - ($ - $$) db %2
;%endmacro
;%idefine PUSHW PUSH STRICT WORD
;%idefine PUSHD PUSH STRICT DWORD
[org 0x7C00]
; https://stanislavs.org/helppc/ ;; BIOS
; https://c9x.me/x86/ ;; Instruction Set
; https://wiki.osdev.org/ ;; OS Development
; absolute address = (segment << 4) + address
; to simulate NES/SNES style memory mapping (banks), only use bits[9..15] ($x000)
JMP 0x0000:_start ; ensure CS = $0000
_start:
CLI ; clear interrupt flag (disable
; interrupts, opposite of 6502)
CLD ; clear direction flag
PUSH CS
POP DS ; prepare for puts / puthexbyte
PUSH CS
POP SS ; set up stack segment
MOV SP, 0x7C00
;; set graphics ;;
MOV AX, 0x0012 ; set screen mode
INT 0x10
MOV AH, 0x0B
MOV BX, 0x0201
INT 0x10
MOV DX, 0x0D22 ; display "LOADING..."
MOV BX, 0x0007
MOV SI, loadstr
CALL putsl
MOV AH, 0x86 ; wait a moment...
MOV CX, 0x000F
INT 0x15
;; load floppy disk ;;
MOV BP, 0x0800 ; if fail, read x times
.loadfailure:
SUB BP, 0x0100 ; decrement # of tries left
MOV AH, 0x02 ; print # of tries left
XOR DX, DX
INT 0x10
MOV DX, BP
CALL puthexbyte
MOV AH, 0x00 ; reset disk system
MOV DL, 0x00
INT 0x13
MOV AX, 0x0201 ; read
MOV CX, 0x0101
XOR DX, DX
PUSHW 0x1800 ; write to $18000 ~ $1FFFF
POP ES
XOR BX, BX
INT 0x13
PUSHF
MOV DH, AH ; show error code
CALL puthexbyte
POPF
JNC .loadsuccess
TEST BP, BP
JNE .loadfailure
MOV DX, 0x0D0F ; read fail;
MOV SI, badload ; print msg
CALL putsl
MOV AH, 0x86 ; wait
MOV CX, 0x001E
INT 0x15
INT 0x18 ; boot windows
.loadsuccess:
MOV DX, 0x0D0F ; read success;
MOV SI, nosystem ; DOS not finished,
CALL putsl ; tell user
MOV AH, 0x86 ; wait
MOV CX, 0x001E
INT 0x15
JMP 0x1000:0x8000 ; boot test
putsl:
; [DX] : (Y,X)
; (AH)
MOV AH, 0x02
INT 0x10 ; set cursor position
puts:
; [DS:SI] : String
; (AX, BX, SI)
MOV AH, 0x0E ; teletype mode
MOV BX, 0x000F ; set white text attribute
.putsloop:
LODSB ; load character from [DS:SI++]
TEST AL, AL ; check if NULL (x86 MOV does not
JE .endputs ; change zero-flag unlike 6502 LDA/LDX/LDY)
INT 0x10 ; print character
JMP .putsloop ; loop until NULL
.endputs:
RET
puthexbyte:
; [DH] : Value
; (AX, DH, BX)
MOV AH, 0x0E
MOV BX, asciihex
MOV AL, DH
SHR AL, 4
XLAT
MOV BX, 0x000F
INT 0x10 ; print character
MOV BX, asciihex
MOV AL, DH
AND AL, 0x0F
XLAT
MOV BX, 0x000F
INT 0x10
RET
asciihex:
db "0123456789ABCDEF", 0
loadstr:
db "LOADING...", 0
badload:
db "Unable to load disk. Attempting to load Windows...", 0
nosystem:
db "Operating System is incomplete. Loading Windows...", 0
tststr:
db "Disk read success. INT 0x20 set success. Jump success.", 0
pad 0x01FE ; pad to end of boot sector
dw 0xAA55 ; floppy disk boot sector signature
; code
PUSHW 0x0000 ; test setting INT
POP DS ; (tested; works when in
MOV [4 * 0x20], DWORD putsl ; boot sector)
MOV DX, 0x0D0D ; test INT by
MOV SI, tststr ; printing
INT 0x20 ; string
MOV AH, 0x86 ; wait
MOV CX, 0x001E
INT 0x15
INT 0x18 ; boot windows
pad 0x0400 ; pad to end of sector 1
;incbin "os.bin"
pad 0x00167FFF ; pad to disk end
db 0x00
Edit:
An explanation on how to convert disk sectors and tracks (ie. CX in INT 13,2) into a "linear address" would be greatly appreciated, as the method I am using to get my code onto a floppy disk has me opening the program HxD and manually copying and pasting my binary onto the the disk.
Also, the disk I am using is 'unformatted' (as far as Windows is concerned).
Also, also, if this changes anything, my PC's BIOS is (msinfo32)"American Megatrends Inc. 5.35, 2008-12-16."
i am using nasm and this is my code :
org 0x7c00
bits 16
section .data
zeichen dw 'hello2'
section .text
mov ax,0x7c00
mov es,ax
mov bh,0
mov bp,zeichen
mov ah,13h
mov bl,00h
mov al,1
mov cx,6
mov dh,010h
mov dl,01h
int 10h
jmp $
times 510 - ($-$$) hlt
dw 0xaa55
it does put the cursor on the right position but it prints nothing.
i load this file with qemu-system-i386.
The int10 ah=13h is a string output and in register es:bp has to be the address of the string
For future reference, since i have been trying to get this working for a long time now, here is a working version!
org 0x7c00
bits 16
xor ax, ax
mov es, ax
xor bh, bh
mov bp, msg
mov ah, 0x13
mov bl, [foreground]
mov al, 1
mov cx, [msg_length]
mov dh, [msg_y]
mov dl, [msg_x]
int 0x10
hlt
foreground dw 0xa
msg db 'Beep Boop Meow'
msg_length dw $-msg
msg_x dw 5
msg_y dw 2
times 510 - ($-$$) db 0
dw 0xaa55
here is a version closest to original.
org 0x7c00
bits 16
; video page number.
mov bh, 0
; ES:BP is the pointer to string.
mov ax, 0x0
mov es, ax
mov bp, msg
; attribute(7 is light gray).
mov bl, 0x7
; write mode: character only, cursor moved.
mov al, 1
; string length, hardcoded.
mov cx, 6
; y coordinate
mov dh, 16
; x coordinate
mov dl, 1
; int 10, 13
mov ah, 0x13
int 0x10
; keep jumping until shutdown.
jmp $
msg dw 'hello2'
times 510 - ($-$$) db 0
dw 0xaa55
Below i have a code that draw 3 circles in 3 different colors.. that is fine..
but how do i addmit a text string ? Thx.
I did some tests on virtualbox (windows), but no luck..
Any ideas to get it worked ?.
BITS 16
ORG 100h
push 0a000h ;Video memory graphics segment
pop es
mov ax, 0013h ;320x200#8bpp
int 10h
push 0Eh ;Blue
push 10 ;cX
push 10 ;cY
push 10 ;Radius
call drawFilledCircle
push 02h ;Blue
push 40 ;cX
push 40 ;cY
push 30 ;Radius
call drawFilledCircle
push 06h ;Blue
push 140 ;cX
push 100 ;cY
push 70 ;Radius
call drawFilledCircle
;Wait for a key
xor ah, ah
int 16h
loc db "KERNEL IMG"
.LOOP:
push cx
mov cx, 0x000B ; eleven character name
mov si, loc
; image name to find
push di
rep cmpsb ; test for entry match
pop di
;je LOAD_FAT
pop cx
add di, 0x0020 ; queue next directory entry
loop .LOOP
;jmp FAILURE
;Restore text mode
mov ax, 0003h
int 10h
;Return
mov ax, 4c00h
int 21h
;Color
;cX
;cY
;R
drawFilledCircle:
push bp
mov bp, sp
sub sp, 02h
mov cx, WORD [bp+04h] ;R
mov ax, cx
mul ax ;AX = R^2
mov WORD [bp-02h], ax ;[bp-02h] = R^2
mov ax, WORD [bp+06h]
sub ax, cx ;i = cY-R
mov bx, WORD [bp+08h]
sub bx, cx ;j = cX-R
shl cx, 1
mov dx, cx ;DX = Copy of 2R
.advance_v:
push cx
push bx
mov cx, dx
.advance_h:
;Save values
push bx
push ax
push dx
;Compute (i-y) and (j-x)
sub ax, WORD [bp+06h]
sub bx, WORD [bp+08h]
mul ax ;Compute (i-y)^2
push ax
mov ax, bx
mul ax
pop bx ;Compute (j-x)^2 in ax, (i-y)^2 is in bx now
add ax, bx ;(j-x)^2 + (i-y)^2
cmp ax, WORD [bp-02h] ;;(j-x)^2 + (i-y)^2 <= R^2
;Restore values before jump
pop dx
pop ax
pop bx
ja .continue ;Skip pixel if (j-x)^2 + (i-y)^2 > R^2
;Write pixel
push WORD [bp+0ah]
push bx
push ax
call writePx
.continue:
;Advance j
inc bx
loop .advance_h
;Advance i
inc ax
pop bx ;Restore j
pop cx ;Restore counter
loop .advance_v
add sp, 02h
pop bp
ret 08h
;Color
;X
;Y
writePx:
push bp
mov bp, sp
push ax
push bx
mov bx, WORD [bp+04h]
mov ax, bx
shl bx, 6
shl ax, 8
add bx, ax ;320 = 256 + 64
add bx, WORD [bp+06h]
mov ax, WORD [bp+08h]
;TODO: Clip
mov BYTE [es:bx], al
pop bx
pop ax
pop bp
ret 06h
times 510-($-$$) db 0 ; Fill the rest with zeros
dw 0xAA55 ; Boot loader signature
but how do i addmit a text string ?
You've decided to use the 320x200 256 colors video mode 13h.
To output text you can use every BIOS function that deals with text output, just like you would do on a text video screen.
This video mode uses an 8x8 font and so you can position the cursor at any of the 40x25=1000 character cells.
Example of writing a red colored capital B at the center of the screen:
mov dx, 0C14h ;DH=12 row, DL=20 column
mov bh, 0 ;BH=0 display page
mov ah, 02h ;AH=02h set cursor position function
int 10h ;video BIOS interrupt
mov bx, 000Ch ;BH=0 display page, BL=12 red
mov ax, 0E42h ;AH=0Eh teletype function, AL=66 capital B
int 10h ;video BIOS interrupt
BITS 16
[ORG 0x7C00]
;ORG 100h
push 0a000h ;Video memory graphics segment
pop es
mov ax, 0013h ;320x200#8bpp
int 10h
push 0Eh ;Blue
push 10 ;cX
push 10 ;cY
push 10 ;Radius
call drawFilledCircle
push 02h ;Blue
push 40 ;cX
push 40 ;cY
push 30 ;Radius
call drawFilledCircle
push 06h ;Blue
push 140 ;cX
push 100 ;cY
push 70 ;Radius
call drawFilledCircle
;Wait for a key
;xor ah, ah
;int 16h
main: ; Label for the start of the main program
mov ax,0x0000 ; Setup the Data Segment register
; Location of data is DS:Offset
mov ds,ax ; This can not be loaded directly it has to be in two steps.
; 'mov ds, 0x0000' will NOT work due to limitations on the CPU
mov si, HelloWorld ; Load the string into position for the procedure.
call PutStr ; Call/start the procedure
;jmp $ ; Never ending loop
; Procedures
PutStr: ; Procedure label/start
; Set up the registers for the interrupt call
mov ah,0x0E ; The function to display a chacter (teletype)
mov bh,0x00 ; Page number
mov bl,0x07 ; Normal text attribute
.nextchar ; Internal label (needed to loop round for the next character)
lodsb ; I think of this as LOaD String Block
; (Not sure if thats the real meaning though)
; Loads [SI] into AL and increases SI by one
; Check for end of string '0'
or al,al ; Sets the zero flag if al = 0
; (OR outputs 0's where there is a zero bit in the register)
jz .return ; If the zero flag has been set go to the end of the procedure.
; Zero flag gets set when an instruction returns 0 as the answer.
int 0x10 ; Run the BIOS video interrupt
jmp .nextchar ; Loop back round tothe top
.return ; Label at the end to jump to when complete
; ret ; Return to main program
;Wait for a key
xor ah, ah
int 16h
push 01h ;Blue
push 100 ;cX
push 90 ;cY
push 140 ;Radius
call drawFilledCircle
;ret
; Data
HelloWorld db ' WELCOME !! Press Enter ',10,10,0
loc db "KERNEL IMG"
.LOOP:
push cx
mov cx, 0x000B ; eleven character name
mov si, loc
; image name to find
push di
rep cmpsb ; test for entry match
pop di
;je LOAD_FAT
pop cx
add di, 0x0020 ; queue next directory entry
loop .LOOP
;jmp FAILURE
;Restore text mode
mov ax, 0003h
int 10h
;Return
mov ax, 4c00h
int 21h
;Color
;cX
;cY
;R
drawFilledCircle:
push bp
mov bp, sp
sub sp, 02h
mov cx, WORD [bp+04h] ;R
mov ax, cx
mul ax ;AX = R^2
mov WORD [bp-02h], ax ;[bp-02h] = R^2
mov ax, WORD [bp+06h]
sub ax, cx ;i = cY-R
mov bx, WORD [bp+08h]
sub bx, cx ;j = cX-R
shl cx, 1
mov dx, cx ;DX = Copy of 2R
.advance_v:
push cx
push bx
mov cx, dx
.advance_h:
;Save values
push bx
push ax
push dx
;Compute (i-y) and (j-x)
sub ax, WORD [bp+06h]
sub bx, WORD [bp+08h]
mul ax ;Compute (i-y)^2
push ax
mov ax, bx
mul ax
pop bx ;Compute (j-x)^2 in ax, (i-y)^2 is in bx now
add ax, bx ;(j-x)^2 + (i-y)^2
cmp ax, WORD [bp-02h] ;;(j-x)^2 + (i-y)^2 <= R^2
;Restore values before jump
pop dx
pop ax
pop bx
ja .continue ;Skip pixel if (j-x)^2 + (i-y)^2 > R^2
;Write pixel
push WORD [bp+0ah]
push bx
push ax
call writePx
.continue:
;Advance j
inc bx
loop .advance_h
;Advance i
inc ax
pop bx ;Restore j
pop cx ;Restore counter
loop .advance_v
add sp, 02h
pop bp
ret 08h
;Color
;X
;Y
writePx:
push bp
mov bp, sp
push ax
push bx
mov bx, WORD [bp+04h]
mov ax, bx
shl bx, 6
shl ax, 8
add bx, ax ;320 = 256 + 64
add bx, WORD [bp+06h]
mov ax, WORD [bp+08h]
;TODO: Clip
mov BYTE [es:bx], al
pop bx
pop ax
pop bp
ret 06h
times 510-($-$$) db 0 ; Fill the rest with zeros
dw 0xAA55 ; Boot loader signature
I have a problem with a TASM based assembly code. I would like to convert a string in the "string" pointer into a decimal number and then print it as a hexadecimal one. However the code prints only the first 2 characters from the right correctly. What may be wrong with this?
concd SEGMENT
ASSUME cs: concd
ORG 100h
main:
mov ax, 0
mov bx, offset string
mov cx, 0
mov dx, 0
mov si, 0
jump:
mov cx, [bx + si]
cmp cx, 0h ;checking if we reached the end of the string
jz exit
mov dx, ax
mov cx, 9
mult:
add ax, dx ;loop for multiplying by 10
loop mult
mov cx, [bx + si]
sub cx, 30h
add ax, cx
inc si
jmp jump
exit:
call hex
mov ah, 04Ch
mov al, 0
int 21h
hex PROC
mov dx, ax
mov cl, 12
jump2:
mov ax, dx
shr ax, cl
and ax, 15
cmp ax, 9
jng t
add ax, 7h
t: add ax, 30h
call putc
sub cl, 4
jnc jump2
RET
hex ENDP
putc PROC
mov ah, 0Eh
int 10h
RET
putc ENDP
string DB "1234", 0h
concd ENDS
END main
I made some small changes, and now it works.
I commented with "phase 1" the changes that it actually did get a character abd did something, and with "phase 2" the changes that corrected the conversion.
Now it's OP's time to figure out what was wrong.
concd SEGMENT
ASSUME cs: concd
ORG 100h
main:
mov ax, cs ;; added - phase 1
mov ds, ax ;; added - phase 1
mov ax, 0
mov bx, offset string
mov cx, 0
mov dx, 0
mov si, 0
jump:
mov ch, 0 ;; Added - phase 2
mov cl, [bx + si] ;; added - phase 2
;mov cx, [bx + si] ;; removed - phase 2
cmp cx, 0h ;checking if we reached the end of the string
jz exit
mov dx, ax
mov cx, 9
mult: ; ax contains the number
;; removed the next 2 lines - phase 2
;add ax, dx ;loop for multiplying by 10
;loop mult
;; added the next 2 lines - phase 2
mov cl, 10
mul cl ; multiply by 10
mov cx, [bx + si]
sub cx, 30h
add ax, cx
inc si
jmp jump
exit:
call hex
mov ah, 04Ch
mov al, 0
int 21h
hex PROC
mov dx, ax
mov cl, 12
jump2:
mov ax, dx
shr ax, cl
and ax, 15
cmp ax, 9
jng t
add ax, 7h
t: add ax, 30h
call putc
sub cl, 4
jnc jump2
RET
hex ENDP
putc PROC
mov ah, 0Eh
int 10h
RET
putc ENDP
string DB "1234", 0h
concd ENDS
END main