flat assembler
Message board for the users of flat assembler.
![]() |
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 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). |
|||
![]() |
|
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 |
|||
![]() |
|
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. |
|||
![]() |
|
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 |
|||
![]() |
|
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 |
|||
![]() |
|
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 |
|||
![]() |
|
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. |
|||
![]() |
|
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 |
|||
![]() |
|
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 ![]() |
|||
![]() |
|
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? |
|||
![]() |
|
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 |
|||
![]() |
|
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 |
|||
![]() |
|
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. |
|||
![]() |
|
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. |
|||
![]() |
|
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 :: |
|||
![]() |
|
Madis731 17 Apr 2006, 11:53
But you would leave wildcard to colouring, because the second byte is a colour-byte
![]() |
|||
![]() |
|
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 :: |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.