我尝试将一些C++代码转换为程序集。该程序使用迭代回溯算法来查找数组的排列,并选择满足某些条件的第一个排列。
C++代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int m,c;
int x=0;
bool verify(vector<int> v, int m){
for(int i = 1;i<=c;i++){
int found=0;
int cnt=0;
for(int j=0;j<v.size();j++){
if(found==1){
cnt++;
if(v[j]==i){
if(cnt<=m)
return false;
cnt=0;
}
}
if(v[j]==i){
found=1;
}
}
}
return true;
}
void permutations(vector<int> s,int m, vector<int> v,vector<int> zeros)
{
int n = s.size();
if (n == 0) {
return;
}
if(n==1){
return;
}
while (1)
{
int j = 0;
for(int i = 0; i < v.size(); i++){
if(v[i]==0){
v[i]=s[j];
j++;
}
}
if(verify(v,m)){
for(int i = 0; i<v.size();i++){
cout<<v[i]<<' ';
}
x=1;
return;
}
else{
for(int i = 0; i<zeros.size();i++){
v[zeros[i]]=0;
}
}
int i = n - 1;
while (s[i-1] >= s[i])
{
if (--i == 0) {
return;
}
}
j = n - 1;
while (j > i && s[j] <= s[i - 1]) {
j--;
}
swap(s[i - 1], s[j]);
reverse (s.begin() + i, s.end());
}
}
int main()
{
cin>>c>>m;
vector<int> v(3*c);
for(int i = 0;i<3*c;i++)
cin>>v[i];
int j =0;
vector<int> str(3*c);
for(int i = 1;i<=c;i++){
str[j]=i;
j++;
str[j]=i;
j++;
str[j]=i;
j++;
}
for(int i=0;i<3*c;i++){
if(v[i]!=0){
for(int k = 0;k<3*c;k++){
if(str[k]==v[i]){
str.erase(str.begin()+k);
break;
}
}
}
}
vector<int> zeros(0);
j=0;
for(int i=0;i<3*c;i++){
if(v[i]==0){
zeros.push_back(i);
j++;
}
}
permutations(str,m,v,zeros);
if(x==0)cout<<-1;
return 0;
}
当我尝试使用输入5 1 1 0 0 0 0 0 3 0 0 0 0 0 0 4 5
运行asm代码时,我会出现Segmentation错误(核心转储(,但当我使用gdb调试代码时,程序成功完成,我甚至不知道从哪里开始查找。
.data
c: .long 0
zeros: .space 400
x: .long 0
sir: .space 400
n: .long 0
m: .long 0
v: .space 400
delim: .asciz " "
formatScanf: .asciz "%400[^n]"
length: .long 0
sirlength: .long 0
j: .long 0
str: .space 400
zero: .long 0
l: .space 4
d: .space 4
check: .long 0
formatPrintf: .asciz "%d "
jnk: .long 0
final: .asciz "n"
formatPrintf2: .asciz "%c"
.text
verify:
pushl %ebx
pushl %esp
pushl %ebp
pushl %esi
pushl %edi
movl $3, %eax
movl %esp, %esi
mul %esi
movl %esi, %eax
movl $0, %ecx
movl $-1, %ebx
jmp for
for:
add $1, %ecx
cmp %ecx, %esp
jl return_verify_true
movl $0, -24(%esp)
movl $0, -28(%esp)
movl $-1, %ebx
jmp for_for
for_for:
add $1, %ebx
cmp %ebx, %ebp
je for
cmp $1, -24(%esp)
je found
jmp not_found
found:
add $1, -28(%esp)
cmp (%edi, %ebx, 4), %ecx
je adevarat
jmp not_found
not_found:
cmp (%edi, %ebx, 4), %ecx
je add1
jmp for_for
adevarat:
movl -28(%esp), %edx
cmp %edx, 12(%esp)
jl return_verify_false
movl $0, -24(%esp)
jmp for_for
return_verify_true:
popl jnk
popl jnk
popl %edi
popl %esp
popl %ebp
popl %esi
popl %edi
add $20, %esp
movl $1, %eax
jmp final_permutations
return_verify_false:
popl jnk
popl jnk
popl %edi
popl %esp
popl %ebp
popl %esi
popl %edi
movl $0, %eax
jmp while1
add1:
add $1, -24(%esp)
jmp for_for
permutations:
pushl %ebx
pushl %esp
pushl %ebp
pushl %esi
pushl %edi
lea v, %edi
lea str, %esi
lea zeros, %edx
sub $20, %esp
cmp $0, 4(%esp)
je return
cmp $1, 4(%esp)
je numaru1
jmp while1
numaru1:
movl %esi, %ecx
movl %ecx, (%edi, %edx,4)
call verify
while1:
movl $0, %ebx
movl $-1, %ecx
for_in_while:
add $1, %ecx
cmp %ecx, %ebp
jl for_in_while_exit
cmp $0, (%edi, %ecx, 4)
je este_zero
jmp for_in_while
este_zero:
movl (%esi, %ebx, 4), %eax
movl %eax, (%edi, %ebx, 4)
add $1, %ebx
jmp for_in_while
for_in_while_exit:
movl $-1, %ebx
call verify
cmp $1, %eax
je crazy
jmp not_crazy
crazy:
add $1, %ebx
cmp %ebx, %ebp
jge crazy_exit
pushl $formatPrintf
pushl (%edi, %ebx, 4)
call printf
popl %edx
popl %edx
jmp crazy
movl $1, check
ret
not_crazy:
add $1, %ebx
cmp %ebx, 4(%esp)
jge crazy_exit
movl (%edx, %ebx, 4), %eax
movl $0, (%edi, %eax, 4)
jmp not_crazy
crazy_exit:
movl %esp, %eax
sub $1, %eax
movl %eax, %ebx
sub $1, %ebx
while2:
movl (%esi, %ebx, 4), %ecx
cmp %ecx, (%esi, %eax, 4)
jl while2_exit
sub $1, %ebx
sub $1, %eax
cmp $0,%ebx
je return
jmp while2
while2_exit:
movl %esp, %ecx
sub $1, %ecx
movl %eax, jnk
while3:
cmp %ecx, %eax
jg break
movl (%esi, %ecx, 4), %eax
cmp %eax, (%esi, %ebx, 4)
jl break
sub $1, %ecx
jmp while3
break:
movl jnk, %eax
sub $1, %eax
movl (%esi, %eax, 4), %edx
movl %ecx, (%esi, %eax, 4)
movl %edx, %ecx
add $1, %eax
lea str, %edi
movl 4(%esp), %ebx
reverse:
cmp %eax, 4(%esp)
je while1
movl (%esi, %eax, 4), %edx
movl (%edi, %ebx, 4), %ecx
movl %ecx, (%esi, %eax, 4)
movl %edx, (%edi, %ebx, 4)
jmp reverse
return:
popl jnk
popl jnk
popl %edi
popl %esp
popl %ebp
popl %esi
popl %edi
add $20, %esp
jmp final_permutations
.global main
main:
pushl $sir
pushl $formatScanf
call scanf
popl %ebx
popl %ebx
pushl $sir
call strlen
popl %ebx
movl %eax, sirlength
movl %eax, length
pushl $delim
pushl $sir
call strtok
popl %ebx
popl %ebx
sub $48, %eax
movl %eax, n
pushl $delim
pushl $0
call strtok
popl %ebx
popl %ebx
sub $48, %eax
movl %eax, m
movl $0, %ecx
lea v, %edi
et_for:
pushl $delim
pushl $0
call strtok
popl %ebx
popl %ebx
sub $48, %eax
movl %eax, (%edi, %ecx, 4)
add $1, %ecx
cmp %ecx, length
jg et_for
movl $1, %eax
lea str, %edi
movl $0, %ecx
et_for2:
movl %eax, (%edi, %ecx, 4)
add $1, %ecx
movl %eax, (%edi, %ecx, 4)
add $1, %ecx
movl %eax, (%edi, %ecx, 4)
add $1, %ecx
add $1, %eax
cmp %eax, n
jg et_for2
movl $0, %ecx
lea v, %edi
movl $0, %esi
movl $0, %eax
movl $0, %ebx
movl $0, j
movl %ebp, x
lea sir, %ebp
movl %esp, d
et_for3:
movl (%edi, %esi, 4), %esp
movl %esp, zero
cmp $0, zero
jne et_for4
jmp et_for3
et_for4:
movl (%edi, %esi, 4), %edx
cmp (%ebp, %ebx, 4), %edx
je erase
cmp %eax, length
jl et_for3
erase:
add $1, j
movl j, %edx
sub $1, j
movl (%ebp, %edx, 4), %esi
movl j, %esi
sub $1, sirlength
add $1, j
movl length, %esi
sub $1, %esi
cmp j, %esi
jg et_for3
movl $0, j
movl $0, %ecx
lea zeros, %esi
et_for5:
cmp $0, (%edi, %ecx, 4)
je egal
add $1, %ecx
cmp length, %ecx
jl et_for5
jmp dupa_egal
egal:
movl %ecx, (%esi, %ecx, 4)
add $1, %ecx
jmp et_for5
dupa_egal:
movl x, %ebp
movl d, %esp
pushl length
pushl m
pushl sirlength
pushl n
call permutations
final_permutations:
popl %ebx
popl %ebx
popl %ebx
popl %ebx
cmp $0, check
je finalfinal
et_exit:
pushl $final
pushl $formatPrintf2
call printf
popl %ebx
popl %ebx
mov $1, %eax
mov $0, %ebx
int $0x80
finalfinal:
pushl $-1
pushl $formatPrintf
call printf
popl %ebx
popl %ebx
jmp et_exit
我甚至不知道从哪里开始寻找
GDB能够进行事后调试。
您所要做的就是查看core
转储(通过在GDB之外运行程序生成(,如下所示:
gdb /path/to/executable /path/to/core
(gdb) where
Peter Cordes的评论解释了为什么程序可以运行";精细";在GDB下,但在GDB外崩溃,反之亦然。