Home > Enterprise >  A program in assembly to make an input string to lowercase
A program in assembly to make an input string to lowercase

Time:11-22

I am trying to write a program in Assembly x86-64 for an intel 64-bit processor. The program should be compiled with gas (GNU assembler) and run on Linux. The problem is to write a program named lowercase that takes an input string and prints the lowercase of that string. It should be compiled like this:

$> echo "STRING" | ./lowercase
   string
$>

I wrote the program but the problem is that it prints spaces infinitely. Who can help me understand why the following code behaves like that?

.section .bss
.comm buf, 1

.section .text
.globl _start

_start:
        mov $65,        %bh
        mov $97,        %ch
        mov $0,         %dh

Loop:
        mov $0,         %rax                    # syscall number for read
        mov $0,         %rdi                    # where to read from: stdin
        mov $buf,       %rsi                    # buffer adr
        mov $1,         %rdx                    # length of the buffer in bytes
        syscall

        cmpb %dh,       buf                     # if read returns 0 (EOF) or less then 0 exit
        jle Exit
        cmpb %bh,       buf                     # if the character is less than 65 (Char A) print it
        jl Write
        cmpb %ch,       buf                     # if the charcter is less than 97 make it lowercase
        jl ToLowercase


Write:
        mov $1,         %rax                    # system call for write
        mov $1,         %rdi                    # file handle for stdout
        mov $buf,       %rsi                    # address of string to output
        mov $1,         %rdx                    # number of bytes
        syscall
        jmp Loop

ToLowercase:
        addb $32,       buf                     # Make the character lowercase
        jmp Write                               # And go back to output it

Exit:
        mov   $60,      %rax                    # system call for exit
        movb  $0,       %dil                    # return code
        syscall

CodePudding user response:

This line:

cmpb %dh,       buf                     # if read returns 0 (EOF) or less then 0 exit

You modified %rdx (thus %dh) with the count argument to syscall. Also, syscall has no contract to preserve %rdx, so this check is invalid.

Also, the return value from syscall (linux, others) is in %rax, so you are checking an undefined value (%dh) with buf? Something more like

cmp $1, %rax
jlt Exit

would test the return from read. Then you need to see if you are in'A'..'Z':

...
mov buf, %dl
cmp $'A', %dl
jl  write
cmp $'Z', %dl
jle ToLowerCase
...
  • Related