我正在编写一个程序,调用2个预先给定的函数min.c和conv.c,当然还有main.c min.s如下:
.file "min.c"
.text
.p2align 4,,15
.globl min
.type min, @function
min:
.LFB0:
.cfi_startproc
cmpl %esi, %edi
movl %esi, %eax
cmovle %edi, %eax
ret
.cfi_endproc
.LFE0:
.size min, .-min
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~16.04~ppa1) 7.4.0"
.section .note.GNU-stack,"",@progbits
转化:
char conv(char *, char *, int);
char conv(char *x, char *h, int n) {
char ret = 0;
int i;
for (i = 0; i < n; i++) {
ret += x[i] * h[n-i-1];
}
return ret;
}
min.c:
int min(int, int);
int min(int a, int b) {
if (a < b) return a;
return b;
}
和转化如下:
.file "conv.c"
.text
.p2align 4,,15
.globl conv
.type conv, @function
conv:
.LFB0:
.cfi_startproc
testl %edx, %edx
jle .L4
movslq %edx, %rax
leaq -1(%rsi,%rax), %rcx
leaq -2(%rsi,%rax), %rsi
leal -1(%rdx), %eax
xorl %edx, %edx
subq %rax, %rsi
.p2align 4,,10
.p2align 3
.L3:
movzbl (%rdi), %eax
subq $1, %rcx
addq $1, %rdi
mulb 1(%rcx)
addl %eax, %edx
cmpq %rcx, %rsi
jne .L3
movl %edx, %eax
ret
.p2align 4,,10
.p2align 3
.L4:
xorl %edx, %edx
movl %edx, %eax
ret
.cfi_endproc
.LFE0:
.size conv, .-conv
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~16.04~ppa1) 7.4.0"
.section .note.GNU-stack,"",@progbits
我的一小段基本代码也试图遵循预先给出的算法:
for i from 0 to n+m-2 do
ladj <- min(i+1, m)
radj <- m - min(m+n-(i+1), m)
result[i] <- conv(x + (i+1-ladj), h + radj, ladj-radj)
所以我写道:
.globl conv_arr
conv_arr:
movq $0, %rax # zero out the result
movq $0, %rbx # %rbx is set to 0 to be the counter for the loop, i.e. int i
addq %rsi, %rbp
addq %rcx, %rbp
subq $2, %rbp # 3 lines of code to set a limit for the counter, i.e. n + m - 2
loop: # loop label
cmpq %rbx, %rbp # comparing to keep the loop in scope from i = 0 to n + m - 2
jle return # jump to return label if the counter reaches the limit
pushq %rdi
pushq %rsi # saving all the registers before calling function min( int, int)
movq %rbx, %r10 # copying the value of %rbx into the value of %r10
addq $1, %r10 # adding 1 to the value of %r10
movq %r10, %rdi # changing the value of %rdi ( in this case the first parameter
# to the function min() ) to i + 1
movq %rcx, %rsi # changing the value of %rsi ( in this case the second parameter to
# the function min() ) to m
call min # calling the function min() with the two parameters %rdi, %rsi
popq %rsi
popq %rdi # restoring the values of %rdi and %rsi to their initial values
movq %rax, %r12 # copying the value of the result from function min() to %r12,
# the register which is now set up to be the value of ladj
pushq %rdi
pushq %rsi # saving the values of %rdi and %rsi before calling function min()
movq %rcx, %rdi # copying the value of %rcx ( int m ) into the value of %rdi
addq %rsi, %rdi # adding the value of %rsi ( int n ) into the value of %rdi
subq %rbx, %rdi # subtracting the value of %rbx ( int i ) from the value of %rdi
subq $1, %rdi # subtracting 1 from the value of %rdi
movq %rcx, %rsi # copying the value of %rcx ( int m ) into the value of %rsi
call min # calling the function min() with two parameters %rdi, %rsi
popq %rsi
popq %rdi # restoring the values of %rdi and %rsi to their initial values
movq %rcx, %r13 # copying the value of %rcx ( int m ) into the value of
# register %r13
subq %rax, %r13 # subtracting the value of %rax ( min( m + n - ( i + 1 ), m ) )
# from the value of %rcx ( m )
movq %r13, %r14 # copying the value of %r13 ( m - min( m + n - ( i + 1 ), m ) # ) into the value of %r14, the register which is now set up
# to be the value of radj
pushq %rdi
pushq %rsi
pushq %rdx
pushq %rcx # saving the values of %rdi, %rsi, %rdx and %rcx before calling
# function conv( char*, char*, int )
addq %rbx, %rdi # adding the value of %rbx ( i ) to the value of %rdi ( char* x )
addq $1, %rdi # adding 1 to the value of %rdi
subq %r12, %rdi # subtracting the value of %r12 ( ladj ) from the value of %rdi
movq %rdx, %rsi # copying the value of %rdx ( char* h ) to the value of %rsi
addq %r14, %rsi # adding the value of %r14 ( radj ) to the value of %rsi
movq %r12, %rdx # copying the value of %r12 ( ladj ) to the value of %rdx
subq %r14, %rdx # subtracting the value of %r14 ( radj ) from the value of %rdx
call conv # calling the function conv() with three parameters %rdi, %rsi
# and %rdx
popq %rcx
popq %rdx
popq %rsi
popq %rdi # restoring the values of %rdi, %rsi, %rdx and %rcx to their # initial values
movq %rax, %r8 # copying the value of %rax ( result after calling function conv() # ) into the value of the index that %r8 ( char* result) is # pointing to
incq %rbx # incrementing the value of %rbx ( i ) by 1
incq %r8 # incrementing the value of %r8 ( char* result ) according to the
# value of %rbx ( i ), i.e. result[i]
jmp loop # jump back to the loop label when all the procedures are done
return: # return label
ret
给出所有评论以跟踪我的尝试,我知道它需要更多的研究和关注。
当我运行程序时,出现了段错误,我用它运行了gdb,它说错误是无法访问地址xxx处的内存:
程序收到信号SIGSEGV,分段错误。
0x0000000000400757 in conv (x=0x601050 <signal> "",
h=0xffffffff80601050 <error: Cannot access memory at address 0xffffffff601050> n=15) at conv.c:8.
8 ret += x[i] * h[n-i-1];
我使用conv.c在行上尝试了断点,并且在计数时它倒退,即,当程序达到n = 3时,它开始返回n = 2,n = 1,然后一直返回到n = -12
****如果有人有任何建议,我将非常感谢****。