【问题标题】:Running linked C object files(compiled from C and x86-64 assembly) on Cygwin shell, no output?在 Cygwin shell 上运行链接的 C 目标文件(从 C 和 x86-64 程序集编译),没有输出?
【发布时间】:2013-01-20 22:28:08
【问题描述】:

正在尝试处理我的汇编语言任务...

有两个文件,hello.c和world.asm,教授要求我们用gcc和nasm编译这两个文件,并将目标代码链接在一起。

我可以在 64 位 ubuntu 12.10 下很好地使用本机 gcc 和 nasm。

但是当我通过 cygwin 1.7 在 64 位 Win8 上尝试同样的事情时(首先我尝试使用 gcc 但不知何故 -m64 选项不起作用,并且由于教授要求我们生成 64 位代码,我谷歌搜索并找到了一个名为 mingw-w64 的包,它有一个编译器 x86_64-w64-mingw32-gcc ,我可以使用 -m64 ),我可以将文件编译为 mainhello.o 和 world.o 并将它们链接到 main。 out 文件,但不知何故,当我输入“./main.out”并等待“Hello world”时,什么也没有发生,没有输出没有错误消息。

因此新用户无法发布图片,对此感到抱歉,这是 Cygwin shell 中发生的屏幕截图:

我只是一个新手,我知道我可以在 ubuntu 下完成任务,但我只是好奇这里发生了什么?

谢谢大家

你好.c

//Purpose:  Demonstrate outputting integer data using the format specifiers of C.
//
//Compile this source file:     gcc -c -Wall -m64 -o mainhello.o     hello.c
//Link this object file with all other object files:  
//gcc -m64 -o main.out mainhello.o world.o
//Execute in 64-bit protected mode:  ./main.out
//

#include <stdio.h>
#include <stdint.h> //For C99 compatability

extern unsigned long int sayhello();

int main(int argc, char* argv[])
{unsigned long int result = -999;
 printf("%s\n\n","The main C program will now call the X86-64 subprogram.");
 result = sayhello();
 printf("%s\n","The subprogram has returned control to main.");
 printf("%s%lu\n","The return code is ",result);
 printf("%s\n","Bye");
 return result;
}

世界.asm

;Purpose:  Output the famous Hello World message.


;Assemble: nasm -f elf64 -l world.lis -o world.o world.asm


;===== Begin code area 

extern printf    ;This function will be linked into the executable by the linker

global sayhello

segment .data    ;Place initialized data in this segment

          welcome db "Hello World", 10, 0
          specifierforstringdata db "%s", 10,


segment .bss    

segment .text   

sayhello:        

;Output the famous message
mov qword rax, 0       
mov       rdi, specifierforstringdata
mov       rsi, welcome
call      printf

;Prepare to exit from this function
mov qword rax, 0                                  
ret;                                              

;===== End of function sayhello     

【问题讨论】:

  • cygwin生成的可执行文件能在linux系统上运行吗?检查文件大小和调试信息。
  • 两种情况下printf() 的调用约定是否相同?你能用main()的反汇编来检查吗?您可以使用 -S 开关使用 gcc 将 C 代码转换为汇编代码。
  • 我会先在第一个 printf 之后添加“fflush(stdout)”——这样,你就可以看到你是否进入了 sayhello。如果这没有帮助,请尝试使用 gdb! Alexey 对调用约定提出了一个很好的观点。 Windows 与 Linux 不同,所以你的参数应该是 RCX、RDX、R8 和 R9,而不是 RSI、RDI 等。不确定你是否需要 eax 中的任何东西。
  • Cygwin 有缺陷且不可靠。如果您想做 Linux 编程,请使用 Linux。
  • 谢谢大家,@MatsPetersson。所以我添加了 fflush(stdout) 它可以帮助打印出第一行,但其余的没有出现。我根据 Mats 更改了一些代码:mov qword rax, 0mov qword rax, 0mov rcx, specifierforstringdatamov rdx, welcomecall printfmov qword rax, 0 虽然它不起作用。我做了更多的谷歌,发现一个有类似问题的线程[stackoverflow.com/questions/561273/…,这可能表明在windows上这样做是不行的..

标签: c assembly cygwin x86-64 output


【解决方案1】:
;Purpose:  Output the famous Hello World message.
;Assemble: nasm -f win64 -o world.o world.asm

;===== Begin code area

extern _printf    ;This function will be linked into the executable by the linker
global _sayhello

segment .data    ;Place initialized data in this segment
          welcome db "Hello World", 0
          specifierforstringdata db "%s", 10, 0

segment .text

_sayhello:
;Output the famous message
sub       rsp, 32 ; shadow space
mov       rcx, specifierforstringdata
mov       rdx, welcome
call      _printf
add       rsp, 32 ; clean up stack

;Prepare to exit from this function
mov qword rax, 0
ret

;===== End of function sayhello

当与问题中的 C 包装器链接并在纯 cmd 窗口中运行时,它可以正常工作:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2017-07-08
    相关资源
    最近更新 更多