汇编程序,用于将输入字符串变为小写

A program in assembly to make an input string to lowercase

我正在尝试用 Assembly x86-64 为英特尔 64 位处理器编写程序。该程序应使用 gas(GNU 汇编器)和 运行 on Linux 编译。问题是编写一个名为 lowercase 的程序,它接受一个输入字符串并打印该字符串的小写字母。 应该这样编译:

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

我写了这个程序,但问题是它无限打印空格。谁能帮我理解为什么下面的代码会这样?

.section .bss
.comm buf, 1

.section .text
.globl _start

_start:
        mov ,        %bh
        mov ,        %ch
        mov [=11=],         %dh

Loop:
        mov [=11=],         %rax                    # syscall number for read
        mov [=11=],         %rdi                    # where to read from: stdin
        mov $buf,       %rsi                    # buffer adr
        mov ,         %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 ,         %rax                    # system call for write
        mov ,         %rdi                    # file handle for stdout
        mov $buf,       %rsi                    # address of string to output
        mov ,         %rdx                    # number of bytes
        syscall
        jmp Loop

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

Exit:
        mov   ,      %rax                    # system call for exit
        movb  [=11=],       %dil                    # return code
        syscall

这一行:

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

您使用系统调用的计数参数修改了 %rdx(因此修改了 %dh)。此外,syscall 没有保留 %rdx 的合同,因此此检查无效。

此外,来自系统调用(linux、其他)的 return 值在 %rax 中,因此您正在使用 buf 检查未定义的值 (%dh)?更像是

cmp , %rax
jlt Exit

将从读取中测试 return。然后你需要看看你是不是在'A'..'Z':

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