flat assembler
Message board for the users of flat assembler.

Index > DOS > number checking and multiple characters

Author
Thread Post new topic Reply to topic
Damnation



Joined: 08 Sep 2005
Posts: 45
Location: England
Damnation
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?
2, how would i get a line of text from a dos input instead of 1 character.
3, how would i change text colour (is it hard?)
4, i've used dos interupts, how would i go about the other methods.

please bare in mind i am a beginner so be gentle and if possible could you add comments

thank you for any reply.

_________________
Regards
Damnation
Post 30 Sep 2005, 17:42
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo
1).
Code:

; not tested but you get the idea
; should beep if you don't enter a digit 0-9
; this code is lameware   Smile

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).
Post 01 Oct 2005, 22:26
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7802
Location: Kraków, Poland
Tomasz Grysztar
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    
Post 01 Oct 2005, 22:30
View user's profile Send private message Visit poster's website Reply with quote
Damnation



Joined: 08 Sep 2005
Posts: 45
Location: England
Damnation
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.
Post 02 Oct 2005, 09:20
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
casey



Joined: 18 Aug 2005
Posts: 35
casey
>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
    
Post 02 Oct 2005, 11:42
View user's profile Send private message Reply with quote
Damnation



Joined: 08 Sep 2005
Posts: 45
Location: England
Damnation
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
Post 02 Oct 2005, 18:32
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
casey



Joined: 18 Aug 2005
Posts: 35
casey
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
    
Post 02 Oct 2005, 21:41
View user's profile Send private message Reply with quote
Damnation



Joined: 08 Sep 2005
Posts: 45
Location: England
Damnation
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.
Post 03 Oct 2005, 06:25
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
casey



Joined: 18 Aug 2005
Posts: 35
casey
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
Post 03 Oct 2005, 08:33
View user's profile Send private message Reply with quote
rea



Joined: 14 Nov 2004
Posts: 92
rea
Quote:
Then the 'times' directive which failed until
I put the colon after the address labels


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
outputbuffer: times 256 db 0


If you do this, I guess you dont need anymore the bss section Wink, bss section is somewhat a "standar" for example elf also understand this section.
Post 03 Oct 2005, 16:05
View user's profile Send private message Reply with quote
casey



Joined: 18 Aug 2005
Posts: 35
casey
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?
Post 03 Oct 2005, 17:30
View user's profile Send private message Reply with quote
rea



Joined: 14 Nov 2004
Posts: 92
rea
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
Post 03 Oct 2005, 17:44
View user's profile Send private message Reply with quote
casey



Joined: 18 Aug 2005
Posts: 35
casey
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
Post 03 Oct 2005, 19:56
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7802
Location: Kraków, Poland
Tomasz Grysztar
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.
Post 03 Oct 2005, 23:10
View user's profile Send private message Visit poster's website Reply with quote
Bitdog



Joined: 18 Jan 2004
Posts: 97
Bitdog
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.
Post 09 Oct 2005, 09:44
View user's profile Send private message Reply with quote
TDCNL



Joined: 25 Jan 2006
Posts: 56
TDCNL
Bitdog wrote:
MOV AX,3
STOSW ;write the char A=65 to the screen quickly


If you're writing one character only, it's faster to use STOSB.

_________________
:: The Dutch Cracker ::
Post 15 Apr 2006, 15:12
View user's profile Send private message Reply with quote
Madis731



Joined: 25 Sep 2003
Posts: 2140
Location: Estonia
Madis731
But you would leave wildcard to colouring, because the second byte is a colour-byte Wink
Post 17 Apr 2006, 11:53
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
TDCNL



Joined: 25 Jan 2006
Posts: 56
TDCNL
Madis731 wrote:
But you would leave wildcard to colouring, because the second byte is a colour-byte Wink


Ah of course! I'm learning this DOS stuff quickly now Very Happy

_________________
:: The Dutch Cracker ::
Post 19 Apr 2006, 19:34
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.