zoukankan      html  css  js  c++  java
  • 汇编语言程序设计读书笔记(2)- 相关工具64位系统篇

    汇编语言程序设计一书,在32位系统下应该不会有什么问题,然而在64位系统下,则会有些不一样的地方。有些程序范例还会汇编错误或者执行错误。

    博主所用系统为CentOS v6.4 x64。本文主要解决32位的汇编程序如何在64位环境下汇编、连接,而不论述64位汇编语言如何设计。

    1. 64位系统下编译32位的C程序

    以程序test5.c为例,程序代码很简单,如下:

    test5.c


    这个C源程序没有什么32位还是64位之说,用gcc编译后,在64位系统下就得到64位的elf文件,执行也不会有问题,如下图所示:

    image_thumb3

    上图用file test5很清楚的看到是64-bit的文件。

    那么怎么编译成32位的程序呢?用-m32参数。会发现有错误,错误如下:

    image_thumb

    对于警告和exit不兼容,可以包含头文件stdlib.h就可以解决。

    对于gnu/stubs-32.h:没有哪个文件或目录,需要安装glibc-devel和glibc-devel.i686。对于CentOS,安装命令为:yum install glibc-develyum install glibc-devel.i686

    yum install glibc-devel,如下图

    image_thumb4

    yum install glibc-devel.i686,如下图:

    image_thumb5

    之后使用-m32编译,就不会再发生问题了。如下图:

    image_thumb6

    上图用file test5很清楚的看到是32-bit的文件。

    总结以上主要有三点:

    灯泡 64位系统下编译32位程序使用-m32参数,即gcc –m32 –o output_file input_file.c

    灯泡 提示隐式声明与内建函数’exit’不兼容的警告,增加#include <stdlib.h>来解决

    灯泡 gnu/stubs-32.h:没有哪个文件或目录的错误,需要安装glibc-devel和glibc-devel.i686来解决

    2. 64位系统下汇编32位的汇编程序

    1). 64位汇编和32位汇编不同

    汇编语言64位和32位是很不一样的,这里提供一份Intel官方的对64位的汇编简单介绍的pdf文档下载: Introduction_to_x64_Assembly。虽然该文档按照微软的MASM的格式来说明的,但是还是可以得到一些我们需要的信息,从该文档中可以知道64位的寄存器已经和32位的不一样了,比如64位寄存器是rax,rbx等,低32位的才是使用eax,ebx。

    对于系统调用,64位系统和32位系统大大不一样了,比如sys_write的系统调用,32位系统和64位系统分别如下:

    32位的sys_write(stdout, str, length)的汇编调用

    32位系统的sys_write(stdout, str, length)的汇编调用

    64位的sys_write(stdout, str, length)的汇编调用

    64位系统的sys_write(stdout, str, length)的汇编调用

    虽然出于兼容性,32位系统的调用仍然可以在64位系统上运行,但两者已经大大不一样了。本文不是论述如何写64位汇编语言的,而是为了解决32位的汇编代码可以在64位环境下运行。

    2). 64位系统下用as和ld汇编32位的汇编程序

    那么怎样在64位系统中汇编32位的汇编程序呢?以以下例子cpuid2.s为例,代码为:

    cpuid2.s

    这个代码的具体实现,后续的章节会介绍。目前只知道是用于输出CPU厂商ID字符串的就行了。

    在64位系统下,如果按照书中所述的那样as和ld,会产生错误,如下图:

    image_thumb1[1]

    说是push操作无效。

    如果不修改源代码为64位的汇编,要解决这个问题,就需要命令64位系统按照32位的去汇编,as参数是--32, ld参数是-m elf_i386。如下图:

    image_thumb2

    file cpuid2可以看到确实是32位的文件,而且执行也没有问题。这里要特别对ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o cpuid2 -L/lib -lc cpuid2.o这行命令进行说明。

    -m elf_i386:表示按照elf_i386的模块进行连接,即32位的。

    -lc: 因为程序中调用了标准的C库函数printf和exit,因此需要连接C动态库libc.so,所以需要参数-lc来指定连接的库文件,一般而言libxxx.so采用-lxxx的参数。

    -L/lib:博主的系统有多个libc.so,包括64位的,32位的,arm结构的,如下图所示,能搜出很多个libc.so。

    image_thumb16

    而/lib/libc.so才是32位x86系统所需要的动态库,所以使用-L/lib来指定库文件的路径,那么-L/lib –lc就指定了连接的是/lib/libc.so。

    -dynamic-linker /lib/ld-linux.so.2:用于运行时动态加载libc.so动态库的。否则执行生成的可执行文件时会出错。

    3). 64位系统下用gcc汇编32位的汇编程序

    还是以上面的cpuid2.s为例,使用gcc -m32的参数进行汇编成32位的系统文件,特别的,这里由于没有main函数,而是用_start做入口点,因此需要使用参数 –nostdlib,如下图:

    image_thumb1

    gcc -nostdlib -m32 -o cpuid2 cpuid2.s -L/lib -lc进行说明。

    -m32:按照32位的编译。

    -nostdlib:如果没有这个参数,gcc会连接gnu库的函数,该函数会以_start为进入点,执行一段程序后,跳到main执行,而这个汇编源程序中用_start做进入点,而且没有main,因此,没有这个参数的话,会提示没有main定义以及重复定义_start的错误。加了这个参数后,则不会去连接gnu函数。

    综上所述,64位系统下汇编32位汇编程序的做法是:

    as --32 –o output_file.o input_file.s

    ld –m elf_i386 –dynamic-linker /lib/ld-linux.so.2 –o output_file –L/path –llibname input_file.s

    或者

    gcc –m32 –nostdlib –o output_file –L/path –llibname input_file.s

  • 相关阅读:
    一致性哈希算法
    Discourse 的标签(Tag)只能是小写的原因
    JIRA 链接 bitbucket 提示错误 Invalid OAuth credentials
    JIRA 如何连接到云平台的 bitbucket
    Apache Druid 能够支持即席查询
    如何在 Discourse 中配置使用 GitHub 登录和创建用户
    Apache Druid 是什么
    Xshell 如何导入 PuTTYgen 生成的 key
    windows下配置Nginx支持php
    laravel连接数据库提示mysql_connect() :Connection refused...
  • 原文地址:https://www.cnblogs.com/kenzhang1031/p/3411044.html
Copyright © 2011-2022 走看看