方法1
如下:
SECTION .bss
Buff resb 1
SECTION .data
SECTION .text
global _start
_start:
nop ; 这个无操作指令让gdb非常高兴
Read: mov eax, 3 ; 指定sys_read系统调用
mov ebx, 0 ; 指定文件描述符0:标准输入
mov ecx, Buff ; 传递即将从中读取数据的缓冲区的地址
mov edx, 1 ; 告诉sys_read从标准输入读入一个字符
int 80h ; 调用sys_read
cmp eax, 0 ; 观察sys_read在EAX寄存器中的返回值
je Exit ; 如果为0(意思是EOF)则跳转到Exit
; 或者不为0,则测试它是否为一个小写字母
cmp byte [Buff], 61h ; 将输入字符与小写字母“a”相比较
jb Write ; 如果在ASCII表中比“a”小,则不是小写字母
cmp byte [Buff], 7Ah ; 将输入字符与小写字母“z”相比较
ja Write ; 如果在ASCII表中比“z”大,则不是小写字母
; 此时我们已经拥有一个小写字母
sub byte [Buff], 20h ; 从小写字母中减去20h,得出相应的大写字符
; 然后将该字符写出到标准输出
Write: mov eax, 4 ; 指定sys_write系统调用
mov ebx, 1 ; 指定文件描述符,1是标准输出
mov ecx, Buff ; 传递要写出的字符的地址
mov edx, 1 ; 传递要写出的字符的数量
int 80h ; 调用sys_write
jmp Read ; 然后跳转到开始处,获取另外一个字符
Exit: mov eax, 1 ; 指定Exit系统调用
mov ebx, 0 ; 返回一个零代码
int 80h ; 进行系统调用来终止程序
方法2
如下:
SECTION .bss
BUFFLEN equ 1024 ; 缓冲区长度
Buff resb BUFFLEN ; 缓冲区文本本身
SECTION .data
SECTION .text
global _start
_start:
nop ; 这个无操作指令让gdb非常高兴
Read: mov eax, 3 ; 指定sys_read系统调用
mov ebx, 0 ; 指定文件描述符,0是标准输入
mov ecx, Buff ; 传递即将从中读取数据的缓冲区的地址
mov edx, BUFFLEN ; 传递一次循环中要读入的字节数
int 80h ; 调用sys_read来填充缓冲区
mov esi, eax ; 复制sys_read的返回值并妥善保管
cmp eax, 0 ; 如果eax为0,则sys_read到了标准输入的结尾
je Done ; 如果(与0相比较)相等则跳转
mov ecx, esi ; 将读入的字节数放入ecx寄存器中
mov ebp, Buff ; 将缓冲区的地址放入ebp寄存器中
dec ebp ; 调整对偏移地址的计数值
; 详细检查缓冲区,并将小写字符转换为大写字符
Scan: cmp byte [ebp+ecx], 61h ; 将输入字符与小写字母“a”相比较
jb Next ; 如果在ASCII表中比“a”小,则不是小写字母
cmp byte [ebp+ecx], 7Ah ; 将输入字符与小写字母“z”相比较
ja Next ; 如果在ASCII表中比“z”大,则不是小写字母
; 此时我们已经拥有一个小写字母
sub byte [ebp+ecx], 20h ; 从小写字母中减去20h,得出相应的大写字符
Next: dec ecx ; 递减字符计数器
jnz Scan ; 如果仍有字符,则继续循环
; 将满满一缓冲区处理过的文本写到标准输出:
Write: mov eax, 4 ; 指定sys_write系统调用
mov ebx, 1 ; 指定文件描述符1:标准输出
mov ecx, Buff ; 传递缓冲区的偏移地址
mov edx, esi ; 传递缓冲区数据的#个字符
int 80h ; 调用sys_write
jmp Read ; 回去继续循环,加载另一满满的缓冲区数据
Done: mov eax, 1 ; 指定Exit系统调用
mov ebx, 0 ; 返回一个零代码
int 80h ; 进行系统调用来终止程序
使用方法:
./uppercaser < inputfile > outputfile