如何解决Scanf继续在我的汇编程序中进行段错误
我整夜都在研究这个程序。我碰巧看到一个有关自我更改代码的Youtube视频,并说这是个坏主意,所以我决定当然要自己组装。几个小时后,尽管使用了硬编码的数字,但实际上我还是可以使用它。没什么奢侈的,只是概念的证明。它接受两个值,现在称为val1和val2,将它们相加,然后将结果打印到屏幕上。但是,如果val1大于val2,则实际上会更改添加到sub的操作码。再次,我让它使用硬编码的值,并且每次我想更改它们时都重新编译。
但是,尽管我并没有全力以赴,但我至少希望从用户那里获得数字,因此可以通过键入不同的数字而不用重新编译而很容易地看到它的工作原理。我的printf函数工作正常,但我尝试了一下,根本无法使scanf工作。每当我碰到它时,它就会断断续续。我认为可能是因为有许多不同形式的scanf取决于参数,并且参数在汇编中的定义不如C中明确,所以我对方法进行了一些更改。我决定制作一个单独的C例程来获取这两个值,也许以后再做些以使打印它们的混乱程度降低。
至此,我已经完成了该函数,可以看到val1和val2,可以进行编译,可以从由汇编程序组成的主例程中调用我的函数,但是就像以前一样,它在scanf上出现了段错误。经过大约六个小时的工作并缺少大量睡眠,我终于在今晚投入了毛巾。但是,当然,首先我必须向您展示我所拥有的。这是我用来获取数字的简单C例程。
#include <stdio.h>
extern long int val1;
extern long int val2;
void get_values() {
printf("Enter two integers:\n");
scanf("%ld",&val1);
scanf("%ld",&val2);
return;
}
如果这还不够,这是我的汇编文件的头。如果可以解决问题,我会展示整个过程。
.global main
.global val1
.global val2
.bss
.lcomm val1,8
.lcomm val2,8
(以及我如何从汇编例程中调用scanf的示例)
.text
movq $scanf_identifier_string,%edi
movq $val1,%esi
call scanf
我觉得这应该很简单,但却使我完全无法接受。我为能够创建一个可以动态覆盖其自身指令的程序而感到非常兴奋,但是让我无法使scanf正常工作有点尴尬。感谢您的帮助。
解决方法
好的,我解决了。导致问题的原因是堆栈对齐,仅此而已。我在一个多小时前就弄明白了,但是想完成我的程序,所以可以在这里发布。请记住,我没有花时间确保scanf返回有效结果,并尽一切可能对其进行了优化。我的目的不是要使它成为新手可以使用,也不是我有史以来最漂亮的编程。我只是想看看我是否可以在程序中更改机器代码,所以我成功了。考虑到这一点,如果您愿意的话,可以提出一些建议,建议如何改进程序设计。
它要求两个数字并有一条指令将它们相加,但是在此之前,它会检查第一个数字是否更大,如果是,则将添加操作码更改为子操作码并进行更改在printf字符串中+到-。一个问题是我必须定义一个特殊的可写文本部分。我用gcc组装它。
.global main
.data
request:
.string "Enter two integers:\n"
scanf_string:
.string "%ld"
result:
.string "%d + %d = %d\n"
opcode:
.string "Opcode: %#x\n"
.bss
.lcomm val1,8
.lcomm val2,8
.section text,"awx"
main:
// Align stack
subq $8,%rsp
// Get our two numbers from user
// (No error checking for now)
xorq %rax,%rax
movq $request,%rdi
call printf
movq $scanf_string,%rdi
movq $val1,%rsi
call scanf
movq $scanf_string,%rdi
movq $val2,%rsi
call scanf
// Load both variables into registers
// and check which is greater
movq (val1),%rsi
movq (val2),%rdx
cmp %rdx,%rsi
jl preinstruction # First number is less,so we add
// If first is greater or equal,change
// operation to subtraction
movq $instruction+1,%rbx
movb (%rbx),%r8b
xorb $0x28,%r8b # Changes add opcode to sub opcode
movb %r8b,(%rbx)
// Change + to - in result string
movq $result+3,%rbx
movb $45,%r8b # 45 is ASCII value for -
movb %r8b,(%rbx)
// Add (or subtract) values and print
preinstruction:
movq %rsi,%rcx
instruction:
addq %rdx,%rcx
xorq %rax,%rax
movq $result,%rdi
call printf
movq $opcode,%rdi
movq $instruction,%rbx
incq %rbx
xor %rsi,%rsi
movb (%rbx),%sil
xorq %rax,%rax
call printf
add $8,%rsp
xorq %rax,%rax
ret
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。