![](/img/trans.png)
[英]Printf gives segmentation fault unless I do a "printf" first - C
[英]printf gives segmentation fault?
我(正如您已经猜到的)是 nasm 编码的新手,我正在尝试在 nasm 程序集中编写这个简单的组合程序(计算组合 (nCr)),类似于我制作的这个 C 代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int n = 9;
int r = 2;
int i = 0;
int npr = 1;
int rfac = 1;
int k = n;
//nPr
while (i<r)
{
npr = npr*(k);
k--;
i++;
}
//r!
while(r>0)
{
rfac = rfac*r;
r--;
}
//nPr/r! = nCr
printf("%d\n", npr/rfac);
return 0;
}
我在 nasm 中的仿汇编代码:
extern printf
SECTION .data
fmt: db "%d", 10, 0 ;format for printf (used once)
n: dq 10 ; 64 bit double var n = 10.000
r: dq 2 ; 64 bit int var r = 3
i: dq 0 ; 64 bit int var i = 0
npr: dq 1 ; 64 bit double var npr = 1.000
rfac: dq 1 ; 64 bit int var npr = 1
SECTION .text ; code section
global main
main:
push rbp ; base pointer
mov rax,[npr] ; load npr
mov rbx,[i] ; load i
mov rcx,[n] ; load n
mov rdx,[r] ; load r for condition checking
;sub rdx,[r] ; subtract n - r
;sub rdx,1 ; subtract (n = n-r) - 1. now we can compare it to rdx
jmp loop1 ; Jump to condition first
cloop1 imul rax,rcx ; multiply the word npr with n
dec rcx ; decrement n
inc rbx ; increment i
loop1 cmp rbx,rdx ; Check the condition
jl cloop1 ; Jump to content of the loop if met
mov rdx,[r] ; load r
mov rcx,[rfac] ; load rfac
mov rbx,0 ; set rbx to 0
jmp loop2 ; Jump to condition first
cloop2 imul rcx,rdx ; multiply the word rfac with r
dec rdx ; decrement r
loop2 cmp rbx,rdx ; Check the condition(0<=r)
jl cloop2 ; Jump to content of the loop if met
diva:
mov rdx,0
mov rax,rax
idiv rcx ; divide rax(npr) by rcx(rfac)
mov rsi,rax ; 1st printf var
xor rax,rax ; make it 0?
call printf ; call the function
pop rbp ; pop the stack
mov rax,0 ; exit code
ret ; return to OS from main
它一直给我段错误所以我调试它:
diva () at ncr.asm:43
43 mov rdx,0
(gdb) info registers
rax 0x5a 90
rbx 0x0 0
rcx 0x2 2
rdx 0x0 0
rsi 0x7ffffffedec8 140737488281288
rdi 0x1 1
rbp 0x400570 0x400570 <__libc_csu_init>
rsp 0x7ffffffedde0 0x7ffffffedde0
r8 0x7fffff3ecd80 140737475693952
r9 0x7fffff3ecd80 140737475693952
r10 0x2 2
r11 0x7 7
r12 0x400400 4195328
r13 0x7ffffffedec0 140737488281280
r14 0x0 0
r15 0x0 0
rip 0x400545 0x400545 <diva>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) next
44 mov rax,rax
(gdb) next
45 idiv rcx ; divide rax(npr) by rcx(rfac)
(gdb) next
46 mov rsi,rax ; 1st printf var
(gdb) next
47 xor rax,rax ; make it 0?
(gdb) next
48 call printf ; call the function
(gdb) next
Program received signal SIGSEGV, Segmentation fault.
__strchrnul_avx2 () at ../sysdeps/x86_64/multiarch/strchr-avx2.S:57
57 ../sysdeps/x86_64/multiarch/strchr-avx2.S: No such file or directory.
(gdb)
从我看来,循环很好,当我调用 printf 函数时,它给了我段错误。
我在某些地方看到他们先推送格式,然后推送函数,然后再调用它。 我试过了,但我认为我做错了。 如果您认为对我的改进有建设性,欢迎对我的代码提出任何建议/批评和彻头彻尾的亵渎(如果需要)。
编辑:将 "%f" 更改为 "%d",这些是 printf 调用之前寄存器中的值:
(gdb) next
48 call printf ; call the function
(gdb) info registers
rax 0x0 0
rbx 0x0 0
rcx 0x2 2
rdx 0x0 0
rsi 0x2d 45
rdi 0x1 1
rbp 0x400570 0x400570 <__libc_csu_init>
rsp 0x7ffffffedde0 0x7ffffffedde0
r8 0x7fffff3ecd80 140737475693952
r9 0x7fffff3ecd80 140737475693952
r10 0x2 2
r11 0x7 7
r12 0x400400 4195328
r13 0x7ffffffedec0 140737488281280
r14 0x0 0
r15 0x0 0
rip 0x400556 0x400556 <diva+17>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
我知道了!!!!
我做到了,我终于解决了!!!
无论如何,这是我使用的东西:
而不是将格式push fmt
为push fmt
,
相反,我阅读了 nasm 文档,看到了一些示例,发现我们必须将格式fmt
存储在rdi
,并将变量按各自的顺序存储在rsi
、 rdx
、 rcx
、 r8
等中。
所以我就是这样做的,BOOM! 在执行时弹出答案。 我的快乐没有字面的界限
修复代码:
extern printf
SECTION .data
fmt: db "nCr = %d", 10, 0 ;format for printf (used once)
n: dq 10 ; 64 bit double var n = 10.000
r: dq 2 ; 64 bit int var r = 3
i: dq 0 ; 64 bit int var i = 0
npr: dq 1 ; 64 bit double var npr = 1.000
rfac: dq 1 ; 64 bit int var npr = 1
SECTION .text ; code section
global main
main:
push rbp ; base pointer
mov rax,[npr] ; load npr
mov rbx,[i] ; load i
mov rcx,[n] ; load n
mov rdx,[r] ; load r for condition checking
;sub rdx,[r] ; subtract n - r
;sub rdx,1 ; subtract (n = n-r) - 1. now we can compare it to rdx
jmp loop1 ; Jump to condition first
cloop1 imul rax,rcx ; multiply the word npr with n
dec rcx ; decrement n
inc rbx ; increment i
loop1 cmp rbx,rdx ; Check the condition
jl cloop1 ; Jump to content of the loop if met
mov rdx,[r] ; load r
mov rcx,[rfac] ; load rfac
mov rbx,0 ; set rbx to 0
jmp loop2 ; Jump to condition first
cloop2 imul rcx,rdx ; multiply the word rfac with r
dec rdx ; decrement r
loop2 cmp rbx,rdx ; Check the condition(0<=r)
jl cloop2 ; Jump to content of the loop if met
diva:
mov rdx,0
mov rax,rax
idiv rcx ; divide rax(npr) by rcx(rfac)
mov rdi,fmt ; storing format
mov rsi,rax ; 1st printf var
mov rax,0 ; make it 0?
call printf ; call the function
pop rbp ; pop the stack
mov rax,0 ; exit code
ret ; return to OS from main
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.