大多数人在高校里面学的第一门汇编语言是基于16位Intel 8086处理器(即8086汇编语言),现在的大多数系统都是32或者64位的,为了实验需要我们一般安装DosBox来作为16位DOS系统模拟器。

计算机类专业一般都会有编译原理的课,课程会详细介绍代码编译的各个阶段:词法分析、语法分析、语义分析、中间代码产生、编译优化与目标代码生成。其中,在“目标代码生成”阶段,现代编译器一般是生成一个汇编文件,博主想要获取的就是基于16位 DOS系统的8086格式的汇编文件。

GCC与VS等主流的编译器都提供了在编译C/C++代码过程中生成汇编指令的功能,详细步骤非常简单,在此不赘述。下面是C语言源代码以及其通过VS 2019与GCC分别生成的汇编指令。

C语言源码:

#include <stdio.h>int main()
{int i, j, n;for (i = 1; i <= 9; i++) {for (j = 1; j <= i; j++)printf("%d × %d = %2d  ", i, j, i * j);printf("\n");}return 0;
}

VS 2019生成汇编:

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.26.28806.0 TITLE c:\users\hadoop001\desktop\vs2019\main2\main2.c.686P.XMMinclude listing.inc.model   flatINCLUDELIB OLDNAMESPUBLIC   ??_C@_0BB@KPGCELHG@?$CFd?5?C?$JH?5?$CFd?5?$DN?5?$CF2d?5?5@ ; `string'
PUBLIC  ??_C@_01EEMJAFIK@?6@             ; `string'
EXTRN   __imp____stdio_common_vfprintf:PROC
EXTRN   __imp____acrt_iob_func:PROC
EXTRN   @__security_check_cookie@4:PROC
;   COMDAT ??_C@_01EEMJAFIK@?6@
CONST   SEGMENT
??_C@_01EEMJAFIK@?6@ DB 0aH, 00H         ; `string'
CONST   ENDS
;   COMDAT ??_C@_0BB@KPGCELHG@?$CFd?5?C?$JH?5?$CFd?5?$DN?5?$CF2d?5?5@
CONST   SEGMENT
??_C@_0BB@KPGCELHG@?$CFd?5?C?$JH?5?$CFd?5?$DN?5?$CF2d?5?5@ DB '%d ', 0c3HDB   097H, ' %d = %2d  ', 00H         ; `string'
CONST   ENDS
PUBLIC  _main
PUBLIC  _printf
PUBLIC  __vfprintf_l
PUBLIC  ___local_stdio_printf_options
COMM    ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9:QWORD                            ; `__local_stdio_printf_options'::`2'::_OptionsStorage
_DATA   ENDS
; Function compile flags: /Ogtp
; File C:\Users\hadoop001\Desktop\VS2019\main2\main2.c
;   COMDAT _main
_TEXT   SEGMENT
_main   PROC                        ; COMDAT; 5    : {push  ebxpush esipush edi; 6    :     int i, j, n;
; 7    :     for (i = 1; i <= 9; i++) mov    esi, 1
$LL4@main:; 8    :     {
; 9    :         for (j = 1; j <= i; j++)mov edi, 1mov   ebx, esinpad    1
$LL7@main:; 10   :             printf("%d × %d = %2d  ", i, j, i * j);push  ebxpush edipush esipush OFFSET ??_C@_0BB@KPGCELHG@?$CFd?5?C?$JH?5?$CFd?5?$DN?5?$CF2d?5?5@call   _printfinc  ediadd  esp, 16                 ; 00000010Hadd  ebx, esicmp edi, esijle SHORT $LL7@main; 11   :         printf("\n");push    OFFSET ??_C@_01EEMJAFIK@?6@call  _printfinc  esiadd  esp, 4cmp   esi, 9jle   SHORT $LL4@main; 12   :     }
; 13   :
; 14   :     return 0;pop   edipop  esixor  eax, eaxpop ebx; 15   : }ret    0
_main   ENDP
_TEXT   ENDS
END

GCC生成汇编:

 .file   "main1.c".text.def    __main; .scl    2;  .type   32; .endef.section .rdata,"dr"
.LC0:.ascii "%d \303\227 %d = %2d  \0".text.globl    main.def    main;   .scl    2;  .type   32; .endef.seh_proc main
main:pushq  %rbp.seh_pushreg    %rbpmovq    %rsp, %rbp.seh_setframe %rbp, 0subq $48, %rsp.seh_stackalloc    48.seh_endprologuecall  __mainmovl  $1, -4(%rbp)jmp .L2
.L5:movl    $1, -8(%rbp)jmp .L3
.L4:movl    -4(%rbp), %eaximull -8(%rbp), %eaxmovl  %eax, %edxmovl  -8(%rbp), %ecxmovl  -4(%rbp), %eaxmovl  %edx, %r9dmovl  %ecx, %r8dmovl  %eax, %edxleaq  .LC0(%rip), %rcxcall    printfincl  -8(%rbp)
.L3:movl    -8(%rbp), %eaxcmpl  -4(%rbp), %eaxjle   .L4movl $10, %ecxcall   putcharincl -4(%rbp)
.L2:cmpl    $9, -4(%rbp)jle .L5movl $0, %eaxaddq    $48, %rsppopq   %rbpret.seh_endproc.ident   "GCC: (GNU) 10.1.0".def   printf; .scl    2;  .type   32; .endef.def  putchar;    .scl    2;  .type   32; .endef

可能是先入为主,我一直好奇:8086汇编表示的目标代码会是什么样子的?之前也试了不少方法,均告失败,昨天一顿操作居然成功了。首先安装DosBox,之后下载TCC 2.0 for DOS(TCC 2.0 for DOS下载地址(侵删!)),将解压后的tc文件夹放在DosBox的安装目录下,如图1所示。

图1 TC 2.0安装目录

为了之后能够操作成功,建议对tc/include下的stdio.h文件做如下修改:

图2 修改文件

如图2所示,即将tc/include/stdio.h第30行的

#include        <stdarg.h>

改为

#include        "include/stdarg.h"

因为上面的代码只包含了stdio.h头文件,因此博主只针对包含stdio.h会产生的问题进行了解决。(可能还有其他坑,哈哈哈!)

修改文件完成后,打开DosBox,进入tc文件夹,运行tcc.exe将C程序汇编为16位的8086汇编指令。在这之前需先将C文件放置在与tcc.exe同一目录下。执行的过程与结果如图3至图6所示。

图3 使用TCC生成汇编代码

图4 TCC 2.0所生成的汇编代码

图5 编译所得汇编代码

图6 链接所得汇编代码

用到的命令总结如下:

tcc -S -ml main1.c
copy main1.asm ..
cd ..
masm main1.asm
link main1.obj

最终得到的汇编代码如下所示:

 ifndef  ??version
?debug  macroendmendif?debug    S "main1.c"
MAIN1_TEXT  segment byte public 'CODE'
DGROUP  group   _DATA,_BSSassume    cs:MAIN1_TEXT,ds:DGROUP
MAIN1_TEXT  ends
_DATA   segment word public 'DATA'
d@ label   byte
d@w    label   word
_DATA   ends
_BSS    segment word public 'BSS'
b@ label   byte
b@w    label   word?debug  C E95359CD50076D61696E312E63?debug  C E9B434CD500F696E636C7564652F737464696F2E68?debug  C E900501D1110696E636C7564652F7374646172672E68
_BSS    ends
MAIN1_TEXT  segment byte public 'CODE'
;   ?debug  L 3
_main   proc    farpush sipush  di
;   ?debug  L 6mov  si,1jmp short @5
@4:
;   ?debug  L 8mov  di,1jmp short @9
@8:
;   ?debug  L 9mov  ax,simul    dipush  axpush  dipush  sipush  dsmov   ax,offset DGROUP:s@push    axcall  far ptr _printfadd  sp,10
@7:inc di
@9:cmp di,sijle    @8
@6:
;   ?debug  L 10push    dsmov   ax,offset DGROUP:s@+17push    axcall  far ptr _printfpop  cxpop   cx
@3:inc si
@5:cmp si,9jle @4
@2:
;   ?debug  L 13xor ax,axjmp    short @1
@1:
;   ?debug  L 14pop dipop   siret
_main   endp
MAIN1_TEXT  ends?debug  C E9
_DATA   segment word public 'DATA'
s@ label   bytedb  37db    100db   32db    195db   151db   32db    37db    100db   32db    61db    32db    37db    50db    100db   32db    32db    0db 10db    0
_DATA   endsextrn   _printf:far
MAIN1_TEXT  segment byte public 'CODE'
MAIN1_TEXT  endspublic  _mainend

从图5与图6可以看出,TCC所生成的8086汇编代码可以通过MASM的汇编,但无法通过LINK的链接,原因是因为C源程序中调用了库函数printf,其在最终生成可执行文件时才会被OS调用相应库函数的机器指令所“填充”,目标代码等于只是做了一个预调用的“标记”。

在Windows 10上将C语言程序转成16位8086汇编代码相关推荐

  1. 使用windows 10 安装中文版语言

    我在使用windows 10 安装中文版语言包的时候,出现了以下报错: a language package is not available 当我去网络上面下载语言安装包的时候,又出现了另外的错误: ...

  2. 如何在没有微软商店的情况下在Windows 10上安装应用程序

    如何在没有微软商店的情况下在Windows 10上安装应用程序 通过微软商店,你可以轻松地在Windows 10设备上安装应用程序,就像使用Google Play或AppleStore一样.IT部门经 ...

  3. Windows 10的中文用户名怎么改成英文

    第一步:快速启用Administrator账户 以管理员模式启动命令提示符(Win+X组合键后就能看到),输入net user administrator /active:yes启用Administr ...

  4. Windows 10的中文用户名怎么改成英文?

    今天有小伙伴询问Windows 10的中文用户名怎么改成英文?其实改名字很简单(开始--控制面板--用户账户--更改用户账户),难就难在后续把中文名称下的文件夹和用户数据也顺利统一到新名称下.鉴于肯定 ...

  5. 此语言无法安装在此计算机,[修复]无法在Windows 10中安装语言包 | MOS86

    我们都知道,如果要使用母语运行Windows 10,则需要在计算机上安装相同的语言包.安装新的语言包被视为可选功能,它通过Windows Update功能完成.要在Windows 10中添加新语言,请 ...

  6. 如何在Windows 10的地图应用程序中获取离线地图

    If you know you're going to be using your PC in a location without an Internet connection, and you n ...

  7. vscode重置应用程序_如何在Windows 10上重置应用程序的数据

    vscode重置应用程序 With Windows 10's Anniversary Update, you can now reset an app's data without actually ...

  8. 如何在Windows 10上管理应用程序权限

    Modern Windows 10 apps have permissions you can control, just like modern iPhone, iPad, and Android ...

  9. 如何在Windows 10上将Bing的每日照片作为墙纸

    Microsoft now offers an official way to set Bing's beautiful homepage photos as your desktop backgro ...

最新文章

  1. c语言编一个dll 用message box 弹出一个对话框,Qt学习之路(17): Qt标准对话框之QMessageBox...
  2. get,put,post,delete含义与区别
  3. 终止线程的三种方法(转)
  4. 95-910-170-源码-FlinkSQL-Flink SQL 中的流和动态表
  5. 【Elasticsearch】针对初学者的Elasticsearch搜索故障排除
  6. (算法)最长回文子串
  7. 物联网技术如何驱动大数据
  8. python网校_《猎豹网校:快速掌握Python系统管理-53讲》
  9. 用java给pdf压缩并加密_Java实现多文件压缩加密并重命名压缩文件对象的方法
  10. 迷你计算机笔记本,世界上最小的笔记本电脑,机身小巧仅有7英寸
  11. css设置全局内边距为0,重置CSS - 将填充和边距设置为0?
  12. tasklist 结束进程_windows
  13. SSH综合项目实战(快递) -- day07 定区关联快递员、搭建前台、客户注册
  14. termux上的c语言编译器,Termux 与 C 基础
  15. git入库基本操作流程
  16. 刷题记录:牛客NC16122郊区春游
  17. STM32F4 FPU浮点运算单元
  18. C语言程序员必读的5本书
  19. pytorch python学习(三)
  20. Python文本分析技巧

热门文章

  1. 批处理添加iis wpg、users对IIS的访问权限
  2. Django学习记录4——urls的简述
  3. [极乐小程序]如何快速打造宠物用品店小程序商城
  4. bios调整服务器性能模式吗,正确设置BIOS,开启睿频加速技术
  5. ORAN专题系列-22:O-RU全球前20的主要供应商调研报告
  6. 绿通科技在创业板通过注册:收入依赖美国市场,张志江为实控人
  7. 一文带你了解芯片制造的6个关键步骤
  8. android webview优酷,063-使用WebView播放优酷视频
  9. Unity3D Shader 入门第一天
  10. 机器学习之父长文反思人工智能,从一个生死攸关的故事说起