【问题标题】:Continuous reading & writing using stdin and stdout in AT&T assembly在 AT&T 汇编中使用标准输入和标准输出进行连续读写
【发布时间】:2017-03-10 20:09:10
【问题描述】:

我有一个任务是在 AT&T Assembly 中编写一个程序,只要你想要使用 Linux 的 stdinstdout 的字节序列,它就可以逐个读写。

它应该是一个凯撒密码扰码器,只将大的拉丁字符(A,B,C,D,...)向前一步(就像 A 到 B,B 到 C,C 到 D,...,Z 到 A )。

因此,就像程序读取序列的第一部分,执行操作以更改字母而其他字符保持不变,将更改的部分写入标准输出,然后读取下一部分,然后一次又一次地做所有事情。

最后它应该通过命令运行程序来处理设置为标准输入和标准输出的文件

>./executable  >output.txt < input.txt

我现在能够编写的是读取一些字符、执行操作、打印输出并要求更多的程序。但是,如果您在输入中输入的字符多于 buf 大小,则会崩溃。

代码如下:

SYSCALL32 = 0x80 

EXIT = 1 
ERR_CODE = 0

STDIN = 0 
READ = 3 

STDOUT = 1 
WRITE = 4  

BUF_SIZE = 80 

.data
textin: .space BUF_SIZE
textout: .space BUF_SIZE

.global _start
_start:
mov $READ, %eax
mov $STDIN, %ebx
mov $textin, %ecx
mov $BUF_SIZE, %edx

int $SYSCALL32 # reading 80 characters (buf_size) of std input

cmp $0, %eax 
je exit #if 0 characters read exit

xorl %esi, %esi #clering iterator for loop

loop:
mov textin(%esi), %al #copying 1 character from textin buf to work with

cmp $'\n', %al
je out 
cmp $'A', %al
jl skip
cmp $'Z', %al
jg skip
je takeCareOfZ

add $1, %al
jmp skip

takeCareOfZ:
mov $'A', %al

skip:
movb %al, textout(%esi)
incl %esi
jmp petla

out:
mov $WRITE, %eax
mov $STDOUT, %ebx
mov $textout, %ecx
mov $BUF_SIZE, %edx

int $SYSCALL32 #writing 80 characters to std output

jmp _start

exit:
mov $EXIT, %eax
mov $ERR_CODE, %ebx

int $SYSCALL32

【问题讨论】:

    标签: linux assembly stdout stdin att


    【解决方案1】:

    这是一个程序版本,它消除了与使用固定大小的缓冲区相关的复杂性。

            .text
            .global _start
    _start:
            # read(STDIN_FILENO, buf, 1)
            movl    $1, %edx    # size_t nbyte
            movl    $buf, %ecx  # void *buf
            movl    $0, %ebx    # int filedes
            movl    $3, %eax    # sys_read
            int     $0x80
    
            cmp     $1, %eax    
            jne     bye         # EOF or read() error
    
            cmp     $'A', (%ecx)
            jl      output      # *buf < 'A'
    
            cmp     $'Z', (%ecx)
            jg      output      # *buf > 'Z'
            je      z           # *buf == 'Z'
    
            incl    (%ecx)      # *buf >= 'A' && *buf < 'Z'
            jmp     output
    
    z:
            movl    $'A', (%ecx)
    
    output:
            # write(STDOUT_FILENO, buf, 1)
            movl    $1, %ebx    # int filedes
            movl    $4, %eax    # sys_write
            int     $0x80
            jmp     _start
    
    bye:
            # exit(0)
            movl    $0, %ebx    # int status
            movl    $1, %eax    # sys_exit
            int     $0x80
    
    .data
    buf:
            .byte 0
    

    示例运行

    $ gcc -nostdlib -m32 caesar.S -o caesar
    $ ./caesar 
    1234
    1234
    ABC1
    BCD1
    Z12BB
    A12CC
    

    使用 gdb 运行示例,一次一条指令。

    【讨论】:

    • 非常感谢 :) 如果您不介意为我说明一切,我有一个问题要问您: 1. 为什么 .byte 后面是 0,它是否重要或可能存在那个用例中有什么? 2. 为什么每次与 %ecx 相关的东西都必须放在括号中?比如为什么cmp $'A', (%ecx),而不是cmp $'A', %ecx
    • buf 是一个 1 字节的缓冲区。初始值 0 从未使用过且无关紧要。 %ecx 等价于 buf(%ecx) 等价于 *buf
    • 我已经包含了一个动画,说明如何使用 gdb 一次观察一条指令对寄存器和内存的更改。
    猜你喜欢
    • 2012-06-08
    • 2012-04-25
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 2021-08-03
    • 2010-12-01
    相关资源
    最近更新 更多