2

对于我的生活,我无法弄清楚为什么这不会打印到屏幕上。不会崩溃或段错误,只是退出。是的,我是新人,事实上正在寻找一位导师,如果有人能提供帮助,将不胜感激。

; Hello World in nasm
;

; Intel Linux bt 2.6.39.4 #1 SMP x86_64 GNU/Linux
; NASM version 2.07
; ld 2.20.1-system.20100303
;
; Compile to 32bit with debugging symbols:
; nasm -g -f elf32 -F dwarf string-w.asm
; ld -g -melf_i386 -o string-w string-w.o
; file string-w.asm

[section .data]
    msg db      "Hello World",0xa,0x0
    len equ     $ - msg

[section .bss]

[section .text]

   global _start

_start:

    push dword len
    push dword msg
    push dword 1    ; Stdout
    mov eax,0x4     ; write
    int 0x80
    ret
    add esp,12      

    push    dword 0
    mov     eax, 0x1     ; exit
    int     0x80

再次,非常感谢任何帮助,如果有人正在寻找学生,我已经准备好做志愿者了。

4

3 回答 3

1

你仍然可以使用 int 0x80,你的问题是你用错了。您不将参数压入堆栈,而是在寄存器中传递参数。这些链接将显示哪些调用使用哪些寄存器: Linux 系统调用表 Linux 系统调用参考

于 2012-10-12T03:08:50.910 回答
1

你所得到的看起来几乎像 BSD 代码 - BSD 将参数推送到堆栈上并使用 int 80h。Linux系统调用采用寄存器中的参数,ebx,ecx,edx(这就是你所需要的),esi,edi......甚至可能是ebp。您不需要ret或清理堆栈。

mov edx, len
mov ecx, msg
mov ebx, 1 ; file descriptor for stdout
mov eax, 4 ; sys_write call number (for 32-bit)
int 80h

mov ebx, 0 ; exit code
mov eax, 1 ; sys_exit call number
int 80h

从 C 库调用write()(有些人声称更可取)......

; nasm -f elf32 myprog.asm
; ld -o myprog myprog.o -I/lib/ld-linux.so.2 -lc -melf_i386
global _start
extern write

section .data
     msg db "Hello World", 10
     len equ $ - msg

section .text
_start:
    push len
    push msg
    push 1
    call write
    add esp, 4 * 3

    mov ebx, 0
    mov eax, 1
    int 80h

您必须以不同的方式链接它。你有正确的想法......事实上你有两个正确的想法,你只是把它们搞混了!:)

不要尝试ret_start标签中提取 - 它不是被调用的,而是被跳转到的!

于 2012-10-12T03:36:06.270 回答
0

好吧,基本上 int 0x80 已被弃用,请改用 SYSENTER。

相关线程,其中包含您正在尝试执行的操作的示例……尽管使用稍微不同的汇编语法编写。

这是很久以前的http://articles.manugarg.com/systemcallinlinux2_6.html

谷歌搜索 sysenter ...或 sysenter vs int 0x80。

于 2012-10-12T03:04:40.410 回答