flat assembler
Message board for the users of flat assembler.
Index
> DOS > number checking and multiple characters |
Author |
|
rugxulo 01 Oct 2005, 22:26
1).
Code: ; not tested but you get the idea ; should beep if you don't enter a digit 0-9 ; this code is lameware BEEP equ 7 org 100h use16 Komenco: mov ah,8 int 21h cmp al,'0' jb Bruo cmp al,'9' jbe Fino Bruo: mov al,BEEP int 29h Fino: int 20h 2). helppc int 21,a 3). helppc int 10,13 (or helppc int 10,9 for single char) 4). for color text without DOS ints? Write directly to the screen (0B800h:0 for CO80). |
|||
01 Oct 2005, 22:26 |
|
Tomasz Grysztar 01 Oct 2005, 22:30
For writing colored text you can use this routines (taken from my kelvar example):
Code: display_character: ; al = character ; bl = color xor bh,bh mov cx,1 mov ah,9 int 10h mov ah,0Eh int 10h ret display_text: ; ds:si - ASCIIZ text ; bl = color xor bh,bh mov cx,1 .display: lodsb or al,al jz .end cmp al,0Dh je .type cmp al,0Ah je .type mov ah,9 int 10h .type: mov ah,0Eh int 10h jmp .display .end: ret |
|||
01 Oct 2005, 22:30 |
|
Damnation 02 Oct 2005, 09:20
thanx for that, i'll toy around with it all later, well tomorrow.
gf has opted for a "no computer day" when she wakes up. |
|||
02 Oct 2005, 09:20 |
|
casey 02 Oct 2005, 11:42
>basically got a few plans for some simple apps
>to hone my skills, and start pushing more asm >into my codes. well i mean use of the language. 1, how would you suggest i check that a character is a number and not a letter? If you look up the ascii character set you will see that 0 to 9 is 48 (30h) to 57 (39h) A - Z 65 (41h) to 90 (5Ah) a - z 97 (61h) to 122 (7Ah) So you check the number range If al > 47 and al < 58 then it's a number 2, how would i get a line of text from a dos input instead of 1 character. You just keep getting one character at a time checking to see if it is a cr (0Dh) and put them into a buffer. point to buffer mov di,buffer Again: get character call GetChar put into buffer mov [di],al : inc di if al != 0dh cmp al,0dh get another one jnz Again 3, how would i change text colour (is it hard?) Depends. Below is an example of directly accessing the text mode memory. 4, i've used dos interupts, how would i go about the other methods. You mean like call your own subroutines? > please bare in mind i am a beginner so be > gentle and if possible could you add comments Code: ; Demonstrates use of direct access to text ram ; at $b800 to print a string at col, row with ; ink and paper color . Default values will be ; used if they are not changed before calling ; the routine. ; Each character uses two memory locations ; starting at $b800. One for the asc character ; and the other for the attribute byte, foreground ; and background colors. org 100h ; equates to save remembering color number BLACK = 0 BLUE = 1 GREEN = 2 CYAN = 3 RED = 4 MAGENTA = 5 BROWN = 6 WHITE = 7 DARKGRAY = 8 LTBLUE = 9 LTGREEN = 10 LTCYAN = 11 LTRED = 12 LTMAGENTA = 13 YELLOW = 14 BRIGHTWHITE = 15 ; ********* START OF MAIN PROGRAM ********* mov ah,0 ; set video mode mov al,2 ; 80 x 25 color int 10h ; video function mov byte [paper],RED ; set paper color call ClearScreen mov byte [col], 10 mov byte [row], 24 ; set col,row to start print mov byte [ink], BLUE ; ink color mov byte [paper], WHITE ;paper color mov dx,szMsg call writeString mov ah,0 int 16h ; wait for keypress mov ah,4Ch mov al,0 int 21h ; return to DOS ; **** END OF MAIN ****** ; ------ START OF SUBROUTINES ------ ; +-----------------------------------------------+ ; | DX = address of string 0 terminated string ! | ; | | ; +-----------------------------------------------+ writeString: push ds si es di push $b800 pop es ; es points to start of video ram mov si,dx ; point si at string to print mov ax,80 mov bh,[row] cmp bh,24 ; check for valid range jg done mul bh mov bl,[col] cmp bl,79 jg done ; check for valid range xor bh,bh ; clear high byte for addition add ax,bx shl ax,1 ; ax = ax * 2 (words not bytes) mov di,ax ; di = (row * 80 + col) * 2 ;compute attribute byte for ah mov ah,[paper] shl ah,4 or ah,[ink] writeLoop: ; WHILE TRUE mov al,[ds:si] ; get character in string inc si ; point to next character or al,al ; condition the flags jz done ; EXIT if it's zero value at end of string mov [es:di],ax ; copy character and attribute to screen ram inc di inc di ; skip two bytes cmp di,4000 ; end of screen ram? jg done ; yep than done jmp writeLoop ; END WHILE done: pop di es si ds ret ; + -----------------------------------+ ; | Fill text ram with space character | ; | set background color to paper | ; | uses ax and cx ; +------------------------------------+ ClearScreen: push di es ; save modified registers push $b800 pop es ; es -> screen text ram mov ah,[paper] shl ah,4 or ah,[ink] mov al,' ' ; space character ; set up loop mov di,0 ; first word of screen mov cx,80 * 25 ; number of words clearLoop: ; DO mov [es:di],ax ; copy attribute and character to screen ram inc di ; inc di ; di = di + 2 (2 bytes to skip) dec cx ; cx = cx - 1 cmp cx,0 ; jnz clearLoop ; UNTIL cx = 0 pop es di ; restore modified registers ret ; data used by program szMsg: db ' HIT [SPACE] KEY TO EXIT ',0 ; zero terminated string (byte array) ; variables and default values col: db 10 ; column (0 to 79) row: db 10 ; row (0 to 24) ink: db 0 paper: db 14 |
|||
02 Oct 2005, 11:42 |
|
Damnation 02 Oct 2005, 18:32
thanx for that i certinally try those out after work
Quote: If al > 47 and al < 58 then it's a number how would i do that in asm i am trying to do this in pure asm. i know how to check then jump. but this and bit.... _________________ Regards Damnation |
|||
02 Oct 2005, 18:32 |
|
casey 02 Oct 2005, 21:41
Look at getnum: in the code below it should give you some
idea how it is done. It is some of my old NASM code when I was learning assembler. I can translate it to FASM for you if you don't know how. I have always believed in designing and understanding how a program works from the top down and used to use BASIC like explanations in the comment column as that was my first programming language. Code: ;example code BITS 16 ORG 0x100 SECTION .text main: mov si,banner call writestring call CRLF ;Carriage Return Line Feed ;--------------------------------------------------------------------- mov cx,1 ;cx = 1 mov BYTE [result],0 ;result = 0 MainLoop: mov si,prompt call writestring ;PRINT "please enter number"; mov ax,cx call PrintNumber ;PrintNumber(ax) mov dl,' ' mov ah,2 int 21h ;PrintString (" ") call ReadNumber ;ReadNumber(ax) add ax,[result] mov [result],ax ;result = result + ax mov si,message call writestring ;PrintString ("result = ") call PrintNumber ;PrintNumber(ax) call CRLF ;crlf inc cx ;cx = cx + 1 cmp cx,9 ;if cx <> 9 then jnz MainLoop ;goto FirstLoop ;--------------------------------------------------------------------- ;exit to DOS mov ax,4C00h int 21h ;END ;*******************************************************; ; AX = value of ASCstring in inputbuffer ; ;*******************************************************; getnum: push bx ;save regs push cx push dx push si sub cx,cx ;clear cx mov bx,10 ;base 10 gnl: mov al,[si] ;get char inc si sub ah,ah ;clear ah sub al,'0' ;convert asc to 0 to 9 (if asc of 0..9) jc gnx ;less than zero cmp al,10 ;less than ten ja gnx ;nope, bail out with answer xchg ax,cx ;else ax = old result, cx = new result mul bx ;old result * 10 add cx,ax ;add new result jmp gnl ;then got get another char gnx: mov ax,cx ;move result to AX pop si pop dx pop cx pop bx ret ;***************************************************; ; outputbuffer = ASCstring of value in ax ; ;***************************************************; putnum: push ax push dx push cx push bx push di mov bx,10 ;bx = base 10 sub cx,cx ;clear cx = number of digits pnl1: sub dx,dx ;clear most significant word for DIV div bx ;divide by 10 add dl,'0' ;remainder in dl make it an ASCII character push dx ;and save it on the stack inc cx ;update the digit count or ax,ax ;is the quotient 0? jnz pnl1 ;now we have all the digits on the stack pnl2: pop ax ;get last digit first mov [di],al ;save it in output buffer inc di loop pnl2 ;cx=cx-1:If cx<>0 then goto pnl2 sub al,al ;al = 0 mov [di],al ;make it a null terminated string pop di pop bx pop cx pop dx pop ax ret ;********************************************; ; inputbuffer = KEYBOARD ; ;********************************************; readstring: push ax push di push bx mov bx,di ;bx = start of buffer to check during backspace rsl: sub ah,ah int 16h ;wait for key function cmp al,13 ;is it a carriage return (Enter key) jz rsx ;yes, then exit cmp al,8 ;is it a backspace jz bkspc ;yes, then do it cmp al,07Fh ;the other backspace jz bkspc ;yes, then do it mov [di],al ;else save char (we should check here for overrun) inc di mov dl,al ;and use dos function to echo it mov ah,2 int 21h jmp rsl ;next character ;backspace routine bkspc: cmp di,bx ;at beginning of text jz rsl ;if so no backspace dec di ;else discard the last input character mov ah,2 ;print mov dl,8 ;backspace action int 21h ;do it mov ah,2 mov dl,' ' int 21h ;print a space mov ah,2 mov dl,8 int 21h ;another backspace over space jmp rsl ; ;exit routine rsx: sub al,al ;clear al mov [di],al ;insert at end of string for null inc di pop bx pop di pop ax ret ;*********************************************; ; SCREEN = output buffer ; ;*********************************************; writestring: push ax push si ; wsl: mov al,[si] inc si or al,al ;al = null? jz wsx ;yes, exit mov dl,al ;else put the char out mov ah,2 int 21h jmp wsl wsx: pop si pop ax ret CRLF: push ax push dx mov ah,2 mov dl,13 int 21h mov dl,10 int 21h pop dx pop ax ret ;----------------------------------------; ; SCREEN = ASCstring of value in ax ; ;----------------------------------------; PrintNumber: mov di,outputbuffer call putnum ; mov si,outputbuffer call writestring ret ;----------------------------------------; ; ax = value of ASCstring from keyboard ; ;----------------------------------------; ReadNumber: mov di,inputbuffer call readstring mov si,inputbuffer call getnum call CRLF ret SECTION .data banner db "My test program",0 ;always have a banner prompt db "Please enter number",0 message db "result = ",0 result dw 0 SECTION .bss inputbuffer resb 256 ;create 256 bytes at run time outputbuffer resb 256 |
|||
02 Oct 2005, 21:41 |
|
Damnation 03 Oct 2005, 06:25
please if u could convert to fasm, as yes as of yet i cannot do it myself : o(
seeing both will be an educating experience. |
|||
03 Oct 2005, 06:25 |
|
casey 03 Oct 2005, 08:33
NASM and FASM are much the same at this level.
The only changes you need to make are, At the top just put, Code: org 100h and delete the directives, SECTION .data and SECTION .bss and change the two lines at the end with, inputbuffer: times 256 db 0 outputbuffer: times 256 db 0 =========================== It took me a while to figure out how to change the .bss section of NASM. At first I tried dup and got, extra characters on line error Then the 'times' directive which failed until I put the colon after the address labels. I don't know if FASM has an equivalent to the NASM .bss section ? - John |
|||
03 Oct 2005, 08:33 |
|
rea 03 Oct 2005, 16:05
Quote: Then the 'times' directive which failed until That is because nasm by default let you put labels without ":" (yes that lead sometimes to somethings, but you can turn ON warnings for this type of labels) Quote: inputbuffer: times 256 db 0 If you do this, I guess you dont need anymore the bss section , bss section is somewhat a "standar" for example elf also understand this section. |
|||
03 Oct 2005, 16:05 |
|
casey 03 Oct 2005, 17:30
So the data definitions,
inputbuffer: times 256 db 0 outputbuffer: times 256 db 0 don't take up any space in the saved .exe file? Which is of course the reason for the .bss isn't it? |
|||
03 Oct 2005, 17:30 |
|
rea 03 Oct 2005, 17:44
They take space 256 bytes each one db/w... stand for declarebyte/word...
But what you will put a data declaration like "db 0" inside bss (before stack segment), is for that I say you dont need anymore the bss section, because your change "db 0 ". fasm should have some like resb for reserve memory (in byte size) for data and is http://flatassembler.net/docs.php?article=manual#_1.3 |
|||
03 Oct 2005, 17:44 |
|
casey 03 Oct 2005, 19:56
Oh dear, I did not read the manual carefully enough.
The directive to reserve memory is rb, rw and so on. Thus if you replace db with rb this works, inputbuffer: times 256 rb 0 outputbuffer: times 256 rb 0 |
|||
03 Oct 2005, 19:56 |
|
Tomasz Grysztar 03 Oct 2005, 23:10
It should be either:
Code: inputbuffer rb 256 or Code: inputbuffer db 256 dup (?) or as an actually the worst variant: Code: inputbuffer: times 256 db ? The "times 256 rb 0" repeats the 256 times the "rb 0", which reserves zero bytes, so it all does nothing. |
|||
03 Oct 2005, 23:10 |
|
Bitdog 09 Oct 2005, 09:44
MOV AX,3
INT 10h ;set video mode 3 = text PUSH WORD 0B800h POP ES ;set ES seg reg at video mem seg XOR DI,DI ;row 0, column 0 MOV AH,1 ; blue on black (color values 0-255 are ok) MOV AL,65 ;character to print STOSW ;write the char A=65 to the screen quickly You can use REPZ STOSB to write a whole string, STOSW is quicker. At 80 characters per line, you can move your imaginary cursor to the next line by ADD DI,160 80 characters and a color for each = 160 bytes per line 0-24 lines = 25 lines There are 0-7 pages you can write to and switch pages to also. You can write to Vmode 13h at seg=0A000h which will print or do graphic pixels in 300x200 with 256 color. |
|||
09 Oct 2005, 09:44 |
|
TDCNL 15 Apr 2006, 15:12
Bitdog wrote: MOV AX,3 If you're writing one character only, it's faster to use STOSB. _________________ :: The Dutch Cracker :: |
|||
15 Apr 2006, 15:12 |
|
Madis731 17 Apr 2006, 11:53
But you would leave wildcard to colouring, because the second byte is a colour-byte
|
|||
17 Apr 2006, 11:53 |
|
TDCNL 19 Apr 2006, 19:34
Madis731 wrote: But you would leave wildcard to colouring, because the second byte is a colour-byte Ah of course! I'm learning this DOS stuff quickly now _________________ :: The Dutch Cracker :: |
|||
19 Apr 2006, 19:34 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.