加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

在64位Linux和64位处理器上运行32位汇编代码:解释异常

发布时间:2020-12-13 17:19:38 所属栏目:Linux 来源:网络整理
导读:我在一个有趣的问题.我忘了我使用64位机器操作系统并写了一个32位汇编代码.我不知道如何写64位代码. 这是Linux上Gnu Assembler(AT T语法)的x86 32位汇编代码. //hello.S#include asm/unistd.h#include syscall.h#define STDOUT 1.datahellostr: .ascii "hell
我在一个有趣的问题.我忘了我使用64位机器&操作系统并写了一个32位汇编代码.我不知道如何写64位代码.

这是Linux上Gnu Assembler(AT& T语法)的x86 32位汇编代码.

//hello.S
#include <asm/unistd.h>
#include <syscall.h>
#define STDOUT 1

.data
hellostr:
    .ascii "hello wolrdn";
helloend:

.text
.globl _start

_start:
    movl $(SYS_write),%eax  //ssize_t write(int fd,const void *buf,size_t count);
    movl $(STDOUT),%ebx
    movl $hellostr,%ecx
    movl $(helloend-hellostr),%edx
    int $0x80

    movl $(SYS_exit),%eax //void _exit(int status);
    xorl %ebx,%ebx
    int $0x80

    ret

现在,这个代码应该在32位处理器上运行良好32位操作系统?我们知道64位处理器向后兼容32位处理器.所以,这也不会是一个问题.出现这个问题是因为系统调用和呼叫机制在64位操作系统32位操作系统.我不知道为什么,但是他们改变了32位linux& 64位linux.

asm / unistd_32.h定义:

#define __NR_write        4
#define __NR_exit         1

asm / unistd_64.h定义:

#define __NR_write              1
#define __NR_exit               60

无论如何,使用宏而不是直接数字是有偿的.确保正确的系统呼叫号码.

当我组装&链接&运行程序.

$cpp hello.S hello.s //pre-processor
$as hello.s -o hello.o //assemble
$ld hello.o // linker : converting relocatable to executable

它不打印helloworld.

在gdb中显示:

>程序退出代码01.

我不知道如何在gdb中进行调试.使用教程我试图调试它,并在每个步骤执行指令检查寄存器的指令.它总是显示“程序退出01”.如果有的话可以告诉我如何调试这将是很棒的.

(gdb) break _start
Note: breakpoint -10 also set at pc 0x4000b0.
Breakpoint 8 at 0x4000b0
(gdb) start
Function "main" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Temporary breakpoint 9 (main) pending.
Starting program: /home/claws/helloworld 

Program exited with code 01.
(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
8       breakpoint     keep y   0x00000000004000b0 <_start>
9       breakpoint     del  y   <PENDING>          main

我试过运行strace.这是它的输出:

execve("./helloworld",["./helloworld"],[/* 39 vars */]) = 0
write(0,NULL,12 <unfinished ... exit status 1>

>在strace的输出中解释write(0,12)系统调用的参数?
>究竟发生了什么?我想知道为什么完全退出exitstatus = 1的原因?
有人可以告诉我如何使用gdb来调试这个程序?
>为什么要更改系统调用号码?
>请妥善更改此程序,以便在本机上正常运行.

编辑:

阅读保罗·R的答案后.我检查了我的文件

claws@claws-desktop:~$file ./hello.o 
./hello.o: ELF 64-bit LSB relocatable,x86-64,version 1 (SYSV),not stripped

claws@claws-desktop:~$file ./hello
./hello: ELF 64-bit LSB executable,statically linked,not stripped

我同意他的看法,这些应该是ELF 32位可重定位&可执行文件.但这并不能解答我的问题.我的所有问题仍然存在疑问.在这种情况下究竟发生了什么?有人可以回答我的问题并提供这个代码的x86-64版本吗?

解决方法

请记住,默认情况下,64位操作系统上的所有内容都倾向于假定为64位.您需要确保(a)在适当的情况下使用32位版本的#includes(b)与32位库链接,(c)构建32位可执行文件.如果您显示您的makefile的内容(如果您有),或者您正在使用的命令来构建此示例,则可能会有所帮助.

FWIW我改变了你的代码(_start – > main):

#include <asm/unistd.h>
#include <syscall.h>
#define STDOUT 1

    .data
hellostr:
    .ascii "hello wolrdn" ;
helloend:

    .text
    .globl main

main:
    movl $(SYS_write),%ebx
    int $0x80

    ret

并建立如下:

$gcc -Wall test.S -m32 -o test

我们有一个32位可执行文件:

$file test
test: ELF 32-bit LSB executable,Intel 80386,for GNU/Linux 2.6.4,dynamically linked (uses shared libs),not stripped

它似乎运行正常:

$./test
hello wolrd

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读