UMBC CMSC 313 -- Array Applications Previous | Next


Array Applications

Reading a Whole Line from the Keyboard

As you should remember from C, when doing keyboard input, you have to define the area where the input will be stored. That means you might have something like:
    char	CharStr[80];
  
To get the input, you might use something like the function gets(). If you need to know how many characters the user typed in, you call strlen(). Seems simple enough. Now we can do the same type of thing in assembly using the system call: read Read is system call number 3 and it needs the file descriptor, STDIN is always 0, the address of where to put it and number of characters to allow. It must also include the new line character (ASCII 10) in the size.

The read system call will return the number of characters read in the EAX register.

Unforunately, the read system call will echo what you type, including the new line.

Now, let's have fun and print that input out backwards.


MAXBUF  EQU     100

section .data

prompt  db      'Please enter a string: ', 10, 0
msg1    db      'Using the first method', 10, 0
msg2    db      'Using the second method', 10, 0
msg3    db      'Using the third method', 10, 0
charout db      '%c',  0
nl	db	10, 0, 0, 0

section .bss

CharStr resb    MAXBUF
GetCnt	resb	1

section .text
    global main                       ;must be declared for linker (ld)

main:                                 ;tell linker entry point
extern	printf 

	push	prompt
	call	printf
	add	esp, 4

; Get the string once

	mov	eax, 3
	mov	ebx, 0
	mov	ecx, CharStr
	mov	edx, MAXBUF
	int	80h
	
	mov	[ GetCnt ], al

; There are three ways to print out the characters in reverse
; order.

;
; First way!!
;
firstway:
	push	msg1
	call	printf
	add	esp, 4
       
        mov     bl, [ GetCnt ]
        test    bl, bl
        jz      Done1
        sub     bh, bh

Reverse1:
        push	dword [CharStr - 1 + ebx]
	push	charout
	call	printf
	add	esp, 8

        dec     bx
        jnz     Reverse1

Done1:
	push	dword [nl]
	push	charout
        call	printf
	add	esp, 4

;
; Second way!!  Question: Could this also be done with the cx register?
;
secondway:        
	push	msg2
	call	printf
	add	esp, 4

        mov     bl, [ GetCnt ]
        test    bl, bl
        jz      Done2
        sub     bh, bh
        mov     edi, CharStr-1

Reverse2:
	push	dword [ ebx + edi ]
	push	charout
	call	printf
	add	esp,8

        dec     bx
        jnz     Reverse2

Done2:
	push	dword [ nl ]
        push	charout
	call	printf
	add	esp, 4

;
; Third way
;
thirdway:
	push	msg3
	call	printf
	add	esp, 4
        
        mov     bl, [ GetCnt ]
        test    bl, bl
        je      Done3
        sub     bh, bh

Reverse3:
	
        push    dword [CharStr - 1 + ebx]
	push	charout
	call	printf
	add	esp, 8

        dec     bx
        jne     Reverse3

Done3:
	push	dword [ nl ]
	push	charout
	call	printf
	add	esp, 8 

        mov     ebx,0   ;successful termination of program
        mov     eax,1   ;system call number (sys_exit)
        int     0x80    ;call kernel
;

Conversion Tables

There is an underrated instruction xlatthat will allow you to convert one byte to another based on a table lookup, where the table is a series of bytes. This requires the AL register to hold the raw value and the BX register should point to a table in member of the corresponding values. When the instruction has executed, AL holds the new value. A simple-to-understand method of converting a binary value in the range of 0 to 16, would be to have a simple table:

section .data
HexDigit   DB       '0123456789ABCDEF'   ;
mybyte     DB       27h                  ;
charout    DB       '%c', 0
section .bss

section .text
    global main                       ;must be declared for linker (ld)

main:                                 ;tell linker entry point
extern	printf 

        mov      ebx, HexDigit        ; Point to the table        
        mov      al, [ mybyte ]       ;                           
        mov      cl, 4                ;                           
        shr      al, cl               ; do the high bits first    
        xlat                          ; Get the ASCII value for this number
	
	push	eax
	push	charout
	call	printf
	add	esp, 8
                       ;                           
        mov      al, [ mybyte ]           ;                           
        and      al, 0Fh              ; do the low bits next      
        xlat                          ; Get the ASCII value for this number

	push	eax
	push	charout
	call	printf
	add	esp, 8

	mov	al, 10
	push	eax
	push	charout
	call	printf
	add	esp, 8


        mov     ebx,0   ;successful termination of program
        mov     eax,1   ;system call number (sys_exit)
        int     0x80    ;call kernel
;



Remember that this only works when everything is able to be reduced into a byte-sized values. Actually, there are ways to force other things into byte-sized value, when the value is an index into another array!


Previous | Next

©2004, Gary L. Burt