Я пишу программу, вызывающую 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
conv.c:
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;
}
и conv.s идет следующим образом:
.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];
Iпробовал точки останова в строках, используя conv.c, и при подсчете он возвращался назад, т. е. когда программа достигала n = 3, он начинал возвращаться к n = 2, n = 1, а затем еще дальше к n = -12 и далее.
**** Если бы у кого-нибудь были какие-то предложения, я бы действительно оценил это ****.