【问题标题】:Assembly- How to input interrupt and save it in register汇编-如何输入中断并将其保存在寄存器中
【发布时间】:2017-12-21 00:00:33
【问题描述】:

我写了一些macros 来获取用户的输入,我需要将输入保存在某个寄存器中。
gdb 告诉我存储的值与输入不同!这是我的代码:

%macro exit 0
    mov eax, 1
    int 0x80
%endmacro


%macro  get_input 0           ; input is a number
push_all_general_purpose_regs
    push_all_general_purpose_regs
    mov eax, 3                ; system call number --> sys_read
    mov ebx, 2                ; file descriptor
    mov ecx, num               
    mov edx, 4
    int 0x80
    sub dword [num], '0'      ; convert character to number : forexample '3'->3
    POP_all_general_purpose_regs
%endmacro


%macro push_all_general_purpose_regs 0
    push eax
    push ebx
    push ecx
    push edx
%endmacro


%macro POP_all_general_purpose_regs 0
    POP edx
    POP ecx
    POP ebx
    POP eax
%endmacro

section .bss
    num resb 4  ;  num is where input will be stored at

section .text
global _start
_start:

    get_input  
    lea ecx, [num] ; now ecx holds the address of input
    mov ebx, [ecx] ; I want to move input to ebx
    finished:
    exit

这是gdb的输出:

(gdb) break finished
Breakpoint 1 at 0x80480ad
(gdb) run
Starting program: /assembly-project/main_project/test_project    /sta/a.out
67

Breakpoint 1, 0x080480ad in finished ()
(gdb) info registers
eax            0x0      0
ecx            0x80490b4        134516916
edx            0x0      0
ebx            0xa3706  669446
esp            0xffffd390       0xffffd390
ebp            0x0      0x0
esi            0x0      0
edi            0x0      0
eip            0x80480ad        0x80480ad <finished>
eflags         0x206    [ PF IF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0      0
gs             0x0      0
(gdb)

正如所见,我的输入是67,但ebx 的值是669446

【问题讨论】:

  • 您的代码只允许单个数字。这也将是 1 个字节,但您加载 4 个。您可以在 bl 中找到您的 6
  • 只是意见......你为什么要引入这些宏?他们会将您的源代码变成调试/审查的噩梦,这通常是汇编开发时间的 60-90%。如果您的目的是节省打字时间,那就忘了吧,这只是总开发时间的一小部分,阅读源代码并理解它是您可以节省最多时间的地方。宏很难阅读,尤其是参数化或嵌套的,因为您要么必须记住其中的所有指令,要么在源代码中向上/向下重新阅读它们。通常简单的call procedure 就足以节省您的打字时间。
  • @Jester 你是对的,我没注意到。
  • @Ped7g 实际上,原始项目比上面编写的代码要大。宏帮助我一次专注于一项任务。
  • IMO 在以后的调试过程中你真的会后悔这种宏,它们会使代码膨胀得很快……尤其是“get_input”是可以以几乎相同的方式使用过程的典型情况(只需在get_input 之前添加call,您就有几乎相同的代码,但在调试器的反汇编中没有膨胀,您会看到类似的call &lt;get_input_address&gt; 代码,而不是20 条不在源代码中直接编写的新指令)。

标签: linux assembly nasm system-calls


【解决方案1】:

669446 = 0xA3706 那是你输入的三个字符,让我给你看。

您的原始输入被读取为三个字节36 37 0A(三个字符'6', '7', '\n')。

.bss 中的第 4 个字节为零,因为.bss 部分在二进制加载+初始化期间被 linux OS 清零。

即地址num 处的内存包含dword 值等于0x000A3736

然后你从 sub dword [num], '0' 中减去 0x00000030,所以结果是值 0x000A3706 ... 也就是十进制的 669446,这正是你得到的。

所以一切正常,就像你写的那样。

要使用sys_read 服务输入多位十进制整数,您必须在循环中逐个字符地解析它们,例如:

result = 0
for (digit : input_string) {  // from first to last input character
    if (!is_valid_digit(digit)) break; // will catch '\n', or other invalid char
    result *= 10;
    result += digit - '0';
}
// here "result" is binary integer value equal to the decimal encoded in string.

【讨论】:

    猜你喜欢
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2012-08-26
    相关资源
    最近更新 更多