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

  • 相关阅读:
    设计模式-1.12备忘录模式
    设计模式-简介
    设计模式-1.9享元模式
    设计模式-1.8组合模式
    设计模式-1.7外观模式
    设计模式-1.6建造者模式(生成器模式)
    设计模式-1.5原型模式
    我在GitHubPage的博客
    奇怪的友链增加啦!
    SSL-OI夏日合宿 杂题 LOJ#6089小Y的背包计数问题 根号分治
  • 原文地址:https://www.cnblogs.com/kenzhang1031/p/3411044.html
Copyright © 2011-2022 走看看