从汇编调用C函数 - 应用程序冻结AT"调用printf"我不知道为什么 [英] Call C function from Assembly -- the application freezes at "call printf" and I have no idea why

查看:193
本文介绍了从汇编调用C函数 - 应用程序冻结AT"调用printf"我不知道为什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将努力在一个大的组装项目,但我现在刚开始学习这个新的语言。我试图做一些简单的例子,就像你可能会发现C ++在高中(和两个数字,一个是素数,等等)。

现在我已经得到了显示所有质数最多n个。问题是,该应用程序冻结在调用printf,我不知道为什么。

您能帮我吗?

  .section伪。数据
prime_number_str:
.asciz%D.section伪的.text。全球_start
_开始:
pushl $ 20个
电话.first_prime_numbers
ADDL $ 4%ESP
pushl $ 0个
调用exit
.first_prime_numbers:#argument第n个数
MOVL 4(%ESP),ECX%的#获取第一个参数
do_test:
pushl%ECX #push函数参数
调用.prime
ADDL $ 4%ESP #restore栈的#if不是素跳转到下一个数
CMPL $ 0,%EAX
JE no_not_prime#PRINT数
pushl%eax中#save EAX
pushl%ECX #first说法
pushl $ prime_number_str #text打印
调用printf
ADDL $ 4%ESP
popl%EAX #restore EAXno_not_prime:
环do_test
RET
.prime:#argument:号码查询
MOVL 4(%ESP),%eax中#获取的第一个参数#divide 2参数
xorl%EDX,EDX%
MOVL $ 2,ECX%
pushl%eax中#save的EAX的值
DIVL%ECX
MOVL%EAX,ECX%的#init计数寄存器
popl%EAX #restore的EAX的值MOVL $ 1,EBX%的#assume说法是首要
test_prime:
#如果ECX == 1,然后返回退出功能
CMPL $ 1,ECX%
JLE RETURN_VALUEpushl%eax中#save EAX的旧值由计数器的值#divide值
xorl%EDX,EDX%
DIVL%ECX的#if提醒是0,则数不是素数
CMPL $ 0%EDX
popl%EAX #restore的EAX的值
JE not_prime
subl $ 1,ECX%反#decrease
JMP test_prime #try下一个区分not_prime:
MOVL $ 0%EBX
RETURN_VALUE:
MOVL%EBX,EAX%
RET


解决方案

这可能是因为你的寄存器都搞砸了所谓的后的printf ,您需要保存寄存器你往往会在来用printf ,然后呼叫后恢复。

这是一些当你做系统调用或其他可能与您的注册坦佩雷电话你应该做的始终。

你也应该看看 GDB (GNU调试器)看起来像你,所以如果你是一个GNU / Linux系统的尝试编码GAS:

  GDB youprogram

,然后运行它,看看它失败。

I will be working on a big Assembly project but am now just starting to learn this new language. I am trying to make some simple examples like you might find for c++ in highschool (sum two numbers, is a number prime, etc).

Now I've got to display all prime numbers up to n. The problem is that the application freezes at "call printf" and I have no idea why.

Can you help me with this?

.section    .data
prime_number_str:
.asciz  "%d "

.section    .text

.global     _start
_start:
pushl   $20
call .first_prime_numbers
addl $4, %esp
pushl $0
call exit


.first_prime_numbers:       #argument first n numbers
movl 4(%esp), %ecx  #get the first argument
do_test:
pushl %ecx      #push function arguments
call .prime 
addl $4, %esp       #restore the stack

#if not prime jump to the next number   
cmpl $0, %eax
je no_not_prime

#print the number
pushl %eax          #save eax
pushl %ecx          #first argument
pushl $prime_number_str     #text to print
call printf
addl $4, %esp
popl %eax           #restore eax

no_not_prime:
loop do_test
ret


.prime:             #argument: number to check
movl 4(%esp), %eax  #get the first argument

#divide the argument by 2   
xorl %edx, %edx             
movl $2, %ecx           
pushl %eax      #save the value of eax
divl %ecx       
movl %eax, %ecx     #init the counter register
popl %eax       #restore the value of eax

movl $1, %ebx       #assume the argument is prime
test_prime:
# if ecx == 1 then return exit the function
cmpl $1, %ecx       
jle return_value

pushl %eax      #save the old value of eax  

#divide the value by the value of counter   
xorl %edx, %edx     
divl %ecx       

#if the reminder is 0 then the number is not prime
cmpl $0, %edx   
popl %eax       #restore the value of eax   
je not_prime


subl $1, %ecx       #decrease counter
jmp test_prime      #try next division

not_prime:
movl $0, %ebx
return_value:
movl %ebx, %eax
ret 

解决方案

It is probably because your registers are all messed up after called printf, you need to save the registers that you tend to use after printf and then restore them after the call.

This is something you should do Always when you do syscall or other calls that might tampere with your registers.

Also you should look into gdb ( gnu debugger ) looks like you are coding GAS so if you are on a gnu / linux system try:

gdb youprogram

and then run it to see where it fails.

这篇关于从汇编调用C函数 - 应用程序冻结AT"调用printf"我不知道为什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆