在Windows 10上将C语言程序转成16位8086汇编代码
大多数人在高校里面学的第一门汇编语言是基于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所示。
为了之后能够操作成功,建议对tc/include下的stdio.h文件做如下修改:
如图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所示。
用到的命令总结如下:
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汇编代码相关推荐
- 使用windows 10 安装中文版语言
我在使用windows 10 安装中文版语言包的时候,出现了以下报错: a language package is not available 当我去网络上面下载语言安装包的时候,又出现了另外的错误: ...
- 如何在没有微软商店的情况下在Windows 10上安装应用程序
如何在没有微软商店的情况下在Windows 10上安装应用程序 通过微软商店,你可以轻松地在Windows 10设备上安装应用程序,就像使用Google Play或AppleStore一样.IT部门经 ...
- Windows 10的中文用户名怎么改成英文
第一步:快速启用Administrator账户 以管理员模式启动命令提示符(Win+X组合键后就能看到),输入net user administrator /active:yes启用Administr ...
- Windows 10的中文用户名怎么改成英文?
今天有小伙伴询问Windows 10的中文用户名怎么改成英文?其实改名字很简单(开始--控制面板--用户账户--更改用户账户),难就难在后续把中文名称下的文件夹和用户数据也顺利统一到新名称下.鉴于肯定 ...
- 此语言无法安装在此计算机,[修复]无法在Windows 10中安装语言包 | MOS86
我们都知道,如果要使用母语运行Windows 10,则需要在计算机上安装相同的语言包.安装新的语言包被视为可选功能,它通过Windows Update功能完成.要在Windows 10中添加新语言,请 ...
- 如何在Windows 10的地图应用程序中获取离线地图
If you know you're going to be using your PC in a location without an Internet connection, and you n ...
- vscode重置应用程序_如何在Windows 10上重置应用程序的数据
vscode重置应用程序 With Windows 10's Anniversary Update, you can now reset an app's data without actually ...
- 如何在Windows 10上管理应用程序权限
Modern Windows 10 apps have permissions you can control, just like modern iPhone, iPad, and Android ...
- 如何在Windows 10上将Bing的每日照片作为墙纸
Microsoft now offers an official way to set Bing's beautiful homepage photos as your desktop backgro ...
最新文章
- c语言编一个dll 用message box 弹出一个对话框,Qt学习之路(17): Qt标准对话框之QMessageBox...
- get,put,post,delete含义与区别
- 终止线程的三种方法(转)
- 95-910-170-源码-FlinkSQL-Flink SQL 中的流和动态表
- 【Elasticsearch】针对初学者的Elasticsearch搜索故障排除
- (算法)最长回文子串
- 物联网技术如何驱动大数据
- python网校_《猎豹网校:快速掌握Python系统管理-53讲》
- 用java给pdf压缩并加密_Java实现多文件压缩加密并重命名压缩文件对象的方法
- 迷你计算机笔记本,世界上最小的笔记本电脑,机身小巧仅有7英寸
- css设置全局内边距为0,重置CSS - 将填充和边距设置为0?
- tasklist 结束进程_windows
- SSH综合项目实战(快递) -- day07 定区关联快递员、搭建前台、客户注册
- termux上的c语言编译器,Termux 与 C 基础
- git入库基本操作流程
- 刷题记录:牛客NC16122郊区春游
- STM32F4 FPU浮点运算单元
- C语言程序员必读的5本书
- pytorch python学习(三)
- Python文本分析技巧