打印寄存器的值来安慰 [英] Print register value to console

查看:465
本文介绍了打印寄存器的值来安慰的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要打印的%RCX 的值直接到控制台,假设ASCII值。我已经通过一些聪明的书籍和教程搜查,但所有使用缓冲区来传递任何东西。是否有可能不用于这一目的创建特殊的缓冲区打印什么?

I want to print the value in %RCX directly to the console, let's say an ASCII value. I've searched through some wise books and tutorials, but all use buffers to pass anything. Is it possible to print anything without creating special buffer for that purpose?

可以说,我在这里(这一切的答案都是脂肪过于复杂,我和使用不同的语法):

lets say i am here (all this answers are fat too complicated to me and use different syntax):

movq $5, %rax
...???(print %rax)

在控制台输出:

\>5

例如,要打印缓冲区我使用code:

in example, to print buffer i use code:

SYSWRITE = 4
STDOUT = 1
EXIT_SUCCESS = 0

.text
buff: .ascii "Anything to print\n"
buff_len = . - buff

movq $SYSWRITE, %eax
mov $STDOUT, %ebx
mov $buff, %ecx
mov $buff_len, %edx

没有C code或不同AS语法究!!!

NO C CODE OR DIFFERENT ASS SYNTAX ALLOWED!!!

推荐答案

这答案是增编弗兰克给出了答案,并利用使用有做转换的机制。

This answer is an addendum to the answer given by Frank, and utilizes the mechanism used there to do the conversion.

您提到在你的问题中注册的%RCX 的。这意味着你正在寻找64位code和您的环境很可能的 GCC / 燃气的(GNU汇编程序),因为基于%通常是AT& T公司的风格preFIX的寄存器。

You mention the register %RCX in your question. This suggests you are looking at 64-bit code and that your environment is likely GCC/GAS (GNU Assembler) based since % is usually the AT&T style prefix for registers.

考虑到这一点我创建了一个快速和肮脏的宏,可以通过内联任何你需要打印一个64位寄存器,64位内存操作数,或GNU大会的32位立即值使用。这个版本是一个概念证明,并可能进行修订,以支持64位立即值。所使用的所有寄存器都是preserved和code也将占对Linux的 64位系统V ABI 的红色区域。

With that in mind I've created a quick and dirty macro that can be used inline anywhere you need to print a 64-bit register, 64-bit memory operand, or a 32-bit immediate value in GNU Assembly. This version was a proof of concept and could be amended to support 64 bit immediate values. All the registers that are used are preserved, and the code will also account for the Linux 64-bit System V ABI red zone.

在code以下被注释掉指出是什么在每一步发生的。

The code below is commented to point out what is occurring at each step.

printmac.inc

.macro memreg_to_hex src            # Macro takes one input
                                    #  src = memory operand, register,
                                    #        or 32 bit constant to print

    # Define the translation table only once for the current object
    .ifndef MEMREG_TO_HEX_NOT_FIRST
        .set MEMREG_TO_HEX_NOT_FIRST, 1
        .PushSection .rodata
            hex_xlat: .ascii "0123456789abcdef"
        .PopSection
    .endif

    add    $-128,%rsp               # Avoid 128 byte red zone
    push   %rsi                     # Save all registers that will be used
    push   %rdi
    push   %rdx
    push   %rcx
    push   %rbx
    push   %rax
    push   %r11                     # R11 is destroyed by SYSCALL

    mov  \src, %rdi                 # Move src value to RDI for processing

    # Output buffer on stack at ESP-16 to ESP-1
    lea    -16(%rsp),%rsi           # RSI = output buffer on stack
    lea    hex_xlat(%rip), %rdx     # RDX = translation buffer address
    xor    %eax,%eax                # RAX = Index into translation array
    mov    $16,%ecx                 # 16 nibbles to print

.align 16
1:
    rol    $4,%rdi                  # rotate high nibble to low nibble
    mov    %dil,%al                 # dil now has previous high nibble
    and    $0xf,%al                 # mask off all but low nibble
    mov    (%rdx,%rax,1),%al        # Lookup in translation table
    mov    %al,(%rsi)               # Store in output buffer
    inc    %rsi                     # Update output buffer address
    dec    %ecx
    jne    1b                       # Loop until counter is 0

    mov    $1,%eax                  # Syscall 1 = sys_write
    mov    %eax,%edi                # EDI = 1 = STDIN
    mov    $16,%edx                 # EDX = Number of chars to print
    sub    %rdx,%rsi                # RSI = beginning of output buffer
    syscall

    pop    %r11                     # Restore all registers used
    pop    %rax
    pop    %rbx
    pop    %rcx
    pop    %rdx
    pop    %rdi
    pop    %rsi
    sub    $-128,%rsp               # Restore stack
.endm

printtest.s

.include "printmac.inc"

.global main
.text
main:
    mov $0x123456789abcdef,%rcx
    memreg_to_hex %rcx               # Print the 64-bit value 0x123456789abcdef
    memreg_to_hex %rsp               # Print address containing ret pointer
    memreg_to_hex (%rsp)             # Print return pointer
    memreg_to_hex $0x402             # Doesn't support 64-bit immediates
                                     #  but can print anything that fits a DWORD
    retq

这可以编译和链接与

gcc -m64 printtest.s -o printtest

所以测试程序的输出看起来像宏不打印行字符的结尾:

The macro doesn't print an end of line character so the output of the test program looks like:

0123456789abcdef00007fff5283d74000007f5c4a080a500000000000000402

0123456789abcdef00007fff5283d74000007f5c4a080a500000000000000402

的存储器地址将是不同的。

The memory addresses will be be different.

由于宏是内联,每次调用整个code将发出的宏。在code是浪费空间。在code的体积可以被移动到目标文件可以包含在链接时。然后存根宏可以换一个呼叫来的主要打印功能。

Since the macros are inlined, each time you invoke the macro the entire code will be emitted. The code is space inefficient. The bulk of the code could be moved to an object file you can include at link time. Then a stub macro could wrap a CALL to the main printing function.

在code不使用的printf ,因为在某些时候我以为我看见你不能使用的 C 库。如果不是这种情况这可以通过调用大大简化的printf 来格式化输出打印64位十六进制值。

The code doesn't use printf because at some point I thought I saw a comment that you couldn't use the C library. If that's not the case this can be simplified greatly by calling printf to format the output to print a 64-bit hexadecimal value.

这篇关于打印寄存器的值来安慰的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆