linux - 汇编:如何将数字转换为ascii并写入显示缓冲区

标签 linux assembly x86-64 gnu-assembler att

我是汇编新手,正在使用 AT&T 语法在 64 位 linux 中编程。如果我将数字 1 存储在寄存器中,如何将其转换为 ascii 字符“A”?例如:

movl $1, %ebx
addl $64, %ebx

我能否将 64 加 1 得到 65(A 的十进制值),然后以某种方式将其转换为“A”并使用 write 系统调用将其发送到缓冲区?

编辑 1:在此处发布我的程序代码。

.section .data

message:
        .long 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

length:
        .long 10

.section .text

.globl _start

_start:

xorq %rdi, %rdi  
xorq %rax, %rax  
xorq %rbx, %rbx  
xorq %rcx, %rcx                  
xorq %rdx, %rdx  
movl length, %edx

loop:

        cmpl %ecx, %edx                 
        je loop_end                     
        movl message(,%rdi,4), %eax     
        addl $64, %eax                  
        pushq %rax                      
        incq %rdi                       
        incq %rcx                       
        jmp loop                        



loop_end:

        cmpq $0, %rcx                   
        je exit                         
        popq %rbx                       
        pushq %rcx
        movq $1, %rax
        movq $1, %rdi
        movq %rbx, %rsi                 
        movl length, %edx
        syscall                         
        popq %rcx
        decq %rcx
        jmp loop_end

exit:

        movq $60, %rax
        movq $0, %rdi
        syscall

最佳答案

我对 AT&T 的语法不是很熟悉,但是按照你习惯的方式反汇编 NASM 就足够了。

您应该尽量避免所谓的硬编码常量,因为它会使您的程序更难维护,尤其是当它的长度为数百甚至数千行时。因此;

            section .data       
Values:     db      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 26, 18, 12, 20, 19, 11
V_Size      equ     $ - Values

比这个更可取

    message:
    .long 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

length:
    .long 10

你做的并没有错,但方法是基于你的计算,而不是汇编程序。正如已经指出的那样,使用完成工作所需的最小数据大小。在这种情况下,char 优于 long

NASM 中的这段代码

        section .text
    global  _start

_start: xor     ecx, ecx
        push    rcx                 ; Applications default return value
        mov      cl, V_Size
        push    rcx
        mov     ebx, Values
        push    rbx

    Next:
        or      byte [ebx], 64
        inc     ebx
        loop    Next

        pop     rsi
        pop     rdx
        pop     rax
        inc      al
        mov     edi, eax
        syscall

        mov     edi, eax
        dec     edi
        mov     eax, edi
        mov      al, 60
        syscall

        section .data       
Values:     db      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 26, 18, 12, 20, 19, 11
V_Size      equ     $ - Values

会产生

ABCDEFGHIJZRLTSK

命令提示符紧接在“K”之后。

            section .data:
 6000d8 01020304 05060708 090a1a12 0c14130b

        section .text:

<_start>:   These two instructions are idiosyncratic to my style of programming and not
            essential to functionality of program. 

  4000b0:   31 c9                   xor    %ecx,%ecx
  4000b2:   51                      push   %rcx

            Setup RCX & RBX for LOOP instruction

  4000b3:   b1 10                   mov    $0x10,%cl
  4000b5:   51                      push   %rcx                 ARG2 to syscall
  4000b6:   bb d8 00 60 00          mov    $0x6000d8,%ebx
  4000bb:   53                      push   %rbx                 ARG1 to syscall

<Next>:     This conforms to the scope of your objective.

  4000bc:   67 80 0b 40             orb    $0x40,(%ebx)         [ebx] += 'A'
  4000c0:   ff c3                   inc    %ebx
  4000c2:   e2 f8                   loop   4000bc <Next>

            ssize_t write (int fd, const void *buf, size_t count);

  4000c4:   5e                      pop    %rsi                 ARG1 = ASCII Pntr
  4000c5:   5a                      pop    %rdx                 ARG2 = # of chars
  4000c6:   58                      pop    %rax
  4000c7:   fe c0                   inc    %al                  SYS_WRITE
  4000c9:   89 c7                   mov    %eax,%edi            ARG0 = STD_OUT
  4000cb:   0f 05                   syscall

            Epilogue: Again, just a method I use.

  4000cd:   89 c7                   mov    %eax,%edi  
  4000cf:   ff cf                   dec    %edi
  4000d1:   89 f8                   mov    %edi,%eax
  4000d3:   b0 3c                   mov    $0x3c,%al
  4000d5:   0f 05                   syscall 

关于linux - 汇编:如何将数字转换为ascii并写入显示缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39501308/

相关文章:

linux - z3以前版本库

c# - 我有一个 C sharp 程序,我可以将它编译为 Linux 服务器的可执行文件,以便我可以在服务器上运行它而无需安装单声道吗?

performance - 我如何从预取内在函数中获得可衡量的好处?

linux - pam_tally2 将成功登录记录为失败

linux - 在linux下使用cp需要什么权限?

c++ - 使用 Visual Studio 2010 在 C++ 中进行内联汇编?

assembly - 为什么某些 SSE "mov"指令指定它们移动浮点值?

c - 为什么gcc在arm汇编中分配了更多的堆栈?

assembly - NASM:验证输入

c - 使用 ptrace 解析 Call 和 Ret。