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

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

问题描述

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



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

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

.data
hellostr:
.asciihello 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& 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 //预处理程序
$ as hello.s -o hello.o //汇编
$ ld hello.o //链接器:将可重定位转换为可执行文件

它没有打印 helloworld



在gdb中显示:




  • 使用代码01退出程序。


我不知道如何在gdb中调试。使用教程我试图调试它,并通过指令检查寄存器在每一步执行指令。它总是向我展示用01退出的计划。


$ b

 (gdb)break _start 
注意:如果有人想告诉我如何调试,断点-10也设置在PC 0x4000b0处。
0x4000b0处的断点8
(gdb)start
功能main未定义。
在将来的共享库加载时使断点处于待处理状态? (y或[n])y
临时断点9(主)正在等待处理。
开始程序:/ home / claws / helloworld

使用代码01退出的程序
(gdb)信息断点
数字类型显示地址什么
8断点保存y 0x00000000004000b0< _start>
9断点删除< PENDING>主要

我试着运行 strace 。这是它的输出:

  execve(./ helloworld,[./helloworld],[/ * 39变量* 0] 
write(0,NULL,12<未完成...退出状态1>




  1. 在strace的输出中解释 write(0,NULL,12)系统调用的参数?

  2. 什么确切正在发生?我想知道为什么恰好它以exitstatus = 1退出?

  3. 有人可以告诉我如何使用gdb来调试这个程序吗?

  4. 为什么他们改变系统调用号码? 编程适当,以便它可以在这台机器上正确运行。

编辑:



在阅读Paul R的答案后,我检查了我的文件

  claws @ claws-desktop:〜 $ file ./hello.o 
./hello.o:ELF 64位LSB可重定位,x86-64,版本1(SYSV),未被剥离

claws @ claws-desktop: 〜$ fi le ./hello
./hello:ELF 64位LSB可执行文件,x86-64,版本1(SYSV),静态链接,未删除

我同意他这些应该是ELF 32位可重定位&可执行文件。但是这并不能回答我的问题。我所有的问题仍然存在问题。这种情况到底发生了什么?有人可以请回答我的问题,并提供这个代码的x86-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:
.asciihello 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位可执行文件:

  $ file test 
test:ELF 32位LSB可执行文件,英特尔80386版本1(SYSV),用于GNU / Linux 2.6.4,动态链接(使用共享库) ,没有剥离

,它似乎运行正常:

  $ ./test 
hello wolrd


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.

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\n";
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

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

#define __NR_write        4
#define __NR_exit         1

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

Its not printing helloworld.

In gdb its showing:

  • Program exited with code 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

I tried running strace. This is its output:

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

  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.

EDIT:

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

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?

解决方案

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 I changed your code slightly (_start -> main):

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

    .data
hellostr:
    .ascii "hello wolrd\n" ;
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

and built it like this:

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

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

and it appears to run OK:

$ ./test
hello wolrd

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

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