在 64 位 Linux & 上运行 32 位汇编代码64 位处理器:解释异常 [英] Running 32 bit assembly code on a 64 bit Linux & 64 bit Processor : Explain the anomaly

查看:25
本文介绍了在 64 位 Linux & 上运行 32 位汇编代码64 位处理器:解释异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个有趣的问题.我忘了我使用的是 64 位机器 &OS 并编写了 32 位汇编代码.我不知道如何编写 64 位代码.

I'm in an interesting problem.I forgot I'm using 64bit machine & OS and wrote a 32 bit assembly code. I don't know how to write 64 bit code.

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

This is the x86 32-bit assembly code for Gnu Assembler (AT&T syntax) on Linux.

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

.data
hellostr:
    .ascii "hello wolrd
";
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 和 linux 之间更改了系统调用号.64 位 Linux.

Now, This code should run fine on a 32bit processor & 32 bit OS right? As we know 64 bit processors are backward compatible with 32 bit processors. So, that also wouldn't be a problem. The problem arises because of differences in system calls & call mechanism in 64-bit OS & 32-bit OS. I don't know why but they changed the system call numbers between 32-bit linux & 64-bit linux.

asm/unistd_32.h 定义:

asm/unistd_32.h defines:

#define __NR_write        4
#define __NR_exit         1

asm/unistd_64.h 定义:

asm/unistd_64.h defines:

#define __NR_write              1
#define __NR_exit               60

无论如何使用宏而不是直接数字是有回报的.它确保正确的系统调用号.

Anyway using Macros instead of direct numbers is paid off. Its ensuring correct system call numbers.

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

when I assemble & link & run the program.

$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 退出".如果有人能告诉我如何调试这个,那就太好了.

I don't know how to debug in gdb. using tutorial I tried to debug it and execute instruction by instruction checking registers at each step. its always showing me "program exited with 01". It would be great if some on could show me how to debug this.

(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.这是它的输出:

I tried running strace. This is its output:

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

  1. 解释strace输出中write(0, NULL, 12)系统调用的参数?
  2. 究竟发生了什么?我想知道为什么完全以 exitstatus=1 退出?
  3. 谁能告诉我如何使用 gdb 调试这个程序?
  4. 他们为什么要更改系统调用号?
  5. 请适当更改此程序,以便它可以在本机上正确运行.
  1. Explain the parameters of write(0, NULL, 12) system call in the output of strace?
  2. What exactly is happening? I want to know the reason why exactly its exiting with exitstatus=1?
  3. Can some one please show me how to debug this program using gdb?
  4. Why did they change the system call numbers?
  5. Kindly change this program appropriately so that it can run correctly on this machine.

阅读 Paul R 的回答后.我检查了我的文件

After reading Paul R's answer. I checked my files

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, x86-64, version 1 (SYSV), statically linked, not stripped

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

I agree with him that these should be ELF 32-bit relocatable & executable. But that doesn't answer my my questions. All of my questions still questions. What exactly is happening in this case? Can someone please answer my questions and provide an x86-64 version of this code?

推荐答案

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

Remember that everything by default on a 64-bit OS tends to assume 64-bit. You need to make sure that you are (a) using the 32-bit versions of your #includes where appropriate (b) linking with 32-bit libraries and (c) building a 32-bit executable. It would probably help if you showed the contents of your makefile if you have one, or else the commands that you are using to build this example.

FWIW 我稍微改变了你的代码(_start -> main):

FWIW I changed your code slightly (_start -> main):

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

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

    .text
    .globl main

main:
    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

并像这样构建它:

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

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

verfied that we have a 32-bit executable:

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

它似乎运行正常:

$ ./test
hello wolrd

这篇关于在 64 位 Linux &amp; 上运行 32 位汇编代码64 位处理器:解释异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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