kvmtool下载编译

git clone https://github.com/kvmtool/kvmtool.git 下载后进入到目录执行make即可。

补码

计算机怎么表示负数?以四位有符号数为例,使用高位作为符号位,最高位为0表示正数,为1表示负数,其余三位用来表示值。在计算机中,我们将这种表示方式称为原码。例如:

十进制 二进制 十进制 二进制
2 0010 -2 1010

使用原码表示时,数字0有两种编码:0000和1000。因此,如果使用原码,在设计系统时就需要额外的电路区分+0和-0更糟糕的是如果一个数的正数相加应为0,2 - 2为例:2 - 2 = 2 + (-2) = 0010 + 1010 = 1100 = -4 这明显不对,也就是说,原码不能正确计算减法。怎么办呢?聪明的人类发现使用补码表示数字就可以加减法了。

即:正数的反码和补码都是原码,负数的反码是除符号位以外按位取反,补码是在反码基础上+1。使用补码重新计算 2 - 2:2 + (-2) = 0010 + 1110 = 0000

ASCII码

计算机用高低电平分别表示0和1,所有的数据在存储和运算时都要使用二进制表示,如果我们想用数字表示文本,就要对每一个文本进行编码,目的就是文本转换成数值。具体用哪些二进制是数字表示哪个符号,美国国家标准协会制定了美国信息交换标准代码(American Standard Code for Information Interchange)简称ASCII。ASCII使用8位编码,最多可以表示256个字符,hello world使用的编码就是为:68 65 6C 6C 6F 77 6F 72 6C 64

写外设指令

操作码 指令 描述
EE out DX,AL 将寄存器AL中的字节输出到寄存器DX中的I/O端口地址

第一列为操作码,第二列为汇编语法描述的指令,第三列是指令意义的详细描述。从描述中我们可以得到,EE操作码它会自动到寄存器AX中读取源操作数,到寄存器DX中读取目的操作数。out为操作码的助记符,AL为8位寄存器,DX是16位寄存器,ASCII码是8位的,串口的地址0x3F8(IBM计算机外设地址)是需要使用16位的表示的。

根据写串口指令的格式,我们的程序流程细化为:在执行EE命令前,将串口地址0x3F8存入寄存器DX,将字符存入寄存器AL。

准备源操作数

由out指令可见,在运行指令之前需要将字符A存储到寄存器AL中。x86提供了数据复制指令mov,用于将数据从原操作数复制到目的操作数。原操作数是一个8位立即数,目的操作数是r8,表示一个8位寄存器。

操作码 指令 描述
B0+rb mov r8,imm8 将一个8位立即数复制到一个8位寄存器

指令编码为(B0+rb)ib。根据x86手册,其中rb表示使用操作码的低三位编码目的操作数,即将目的操作寄存器r8的编码嵌入操作吗的低三位。寄存器AL对应的编码为0,因此B0+rb最终编码为B0。

指令编码中的ib对应原操作数,其中i表示立即数,b表示立即数的宽度是一个字节。所以,ib表示跟在操作码之后的是一个8位立即数,和字符对应的ASCII码组合最终(B0+rb)ib的编码分别为:B068 B065 B06C B06C B06F B077 B06F B072 B06C B064。

准备目的操作数

我们需要将串口地址写到寄存器DX中,实质是将一个16位立即数复制到一个16位寄存器, 这显然还是一个数据复制操作

操作码 指令 描述
B8+rw mov r16,imm16 将一个16位立即数复制到一个16位寄存器

这个格式mov指令也接受两个操作数,只不过是16位的。指令编码中的rw表示使用操作码的低三位编码目的操作数,即将目的操作寄存器r16的编码嵌入操作码的低三位。根据x86手册,寄存器DX对应的编码为2,因此B8+rw编码为BA。

指令编码的iw中的i表示立即数,w表示立即数的宽度是一个字,即两个字节。所以iw表示跟在操作码之后的是一个16位立即数,这里即串口地址。不过x86处理器使用小端模式,所以最终(B8+rw)iw的编码为BAF803。

跳转指令

我们的程序循环向串口输出字符串helloworld,在向串口输出后,需要跳转到程序开始的位置,因此需要一个跳转指令jmp,格式如下。

操作码 指令 描述
EB cb jmp rel8 跳转到指令指针+rel8的位置

jmp指令后接一个rel8。rel是relative的缩写,表示相对的意思,8代表8位,因此可以跳转到相对这条指令-128~127的范围。在指令编码中操作码EB之后“cb”就是这个8位的相对偏移。

如果我们想让指令指针指向程序开头,即B0所在的内存地址,那么jmp需要向后跳转35个字节。因为是向后跳转,所以是-35,又因为计算机中使用的是补码,所以我们需要转换一下,根据原码转补码的规则-35的原码是10100011,补码就为11011101,使用16进制表示,即DD。

至此,我们就完成了这段程序的机器语言编码:

ba f8 03
b0 68
ee
b0 65
ee
b0 6c
ee
b0 6c
ee
b0 6f
ee
b0 77
ee
b0 6f
ee
b0 72
ee
b0 6c
ee
b0 64
ee
eb dd

创建程序文件

我们使用vim以二进制模式打开一个文件,vim -b hello_world.bin。按i进入插入模式,然后输入我们的代码

。输入完成后,按下ESC返回标准模式。在标准模式下按下“:”键,进入命令行模式。在“:”的后面输入将16进制转为二进制命令:

:%! xxd -p -r

"%"表示整个文件内容,”%!“一起使用表示将整个文件内容作为后面xxd的输入,然后使用xxd从16进制转为二进制的输出替换整个文件内容。-p 表示不需要任何格式,-r意为反过来。最后输入:“wq”保存退出

使用kvmtool运行程序

sudo kvmtool/lkvm run -c 1 -k hello_world.bin

机器语言编写helloworld的更多相关文章

  1. Hadoop学习笔记(5) ——编写HelloWorld(2)

    Hadoop学习笔记(5) ——编写HelloWorld(2) 前面我们写了一个Hadoop程序,并让它跑起来了.但想想不对啊,Hadoop不是有两块功能么,DFS和MapReduce.没错,上一节我 ...

  2. 开天辟地-用visualstudio2010编写helloworld

    安装好visual之后,创建新项目 向源文件添加helloworld.cpp 编写helloworld代码,编译运行即可 在运行时候出现一个错误,错误和解决方法如下:

  3. 运维开发笔记整理-使用Django编写helloworld

    运维开发笔记整理-使用Django编写helloworld 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.创建Django项目 1>.创建Django项目 djang ...

  4. X86平台下用汇编写"HelloWorld"

    首先需要安装一个汇编器,我用的是Nasm,这个汇编器在Linux下安装还是很简单的. Nasm下载地址http://www.nasm.us/pub/nasm/releasebuilds/ 在下载之后对 ...

  5. Android环境搭建和编写helloworld

    一.配置jdk环境(学过java的请无视) 1.安装jdk jdk下载地址:http://www.oracle.com/technetwork/cn/java/javase/downloads/jdk ...

  6. Hadoop教程之编写HelloWorld(2)

    前面我们写了一个Hadoop程序,并让它跑起来了.但想想不对啊,Hadoop不是有两块功能么,DFS和MapReduce.没错,上一节我们写了一个MapReduce的HelloWorld程序,那这一节 ...

  7. 用记事本编写helloworld文件但是javac时报错

    刚开始编写第一个java文件时遇到的错误: javac HelloWorld.java HelloWorld.java:1: 错误: 写入HelloWorld时出错: HelloWorld.class ...

  8. 全志A33 lichee 搭建Qt App开发环境编写helloworld

    开发平台 * 芯灵思SinlinxA33开发板 淘宝店铺: https://sinlinx.taobao.com/ 嵌入式linux 开发板交流 QQ:641395230 Step 1 在虚拟机(Ce ...

  9. Linux安装jdk,编写helloworld程序

    今天学习了Linux安装jdk,做个笔记记录一下. 第一步,确定Linux是32位的还是64位的,然后到oracle官网上下载对应版本的jdk,一般下载.tar.gz文件.查看Linux的版本的命令是 ...

  10. 【SpringBoot】02.编写HelloWorld

    1.编写一个返回HelloWorld的Controller @Controller public class HelloWorld { @ResponseBody @RequestMapping(&q ...

随机推荐

  1. win32 - 使用GDI+播放gif图片

    今天做case的时候遇到一个这样的问题,故记录下来. Codeproject有类似的案例,不过是使用的MFC模板编译的. 因为我们只需要win32程序,所以就....代码如下: CodeProject ...

  2. 7z命令

    文件解压缩命令 语法格式:7z 参数 文件名 常用参数 a 向压缩包中添加文件 t 测试压缩包的完整性 d 从压缩包中删除文件 u 更新压缩包中的文件 e 从压缩包中提取文件 x 解压文件时保留绝对路 ...

  3. ThreadPoolExecutor和Executors的区别

    Executors创建的线程有两类 newFixedThreadPool和newSingleThreadExecutor,队列数量弹性,创建的线程的队列最大值为INTEGER.max容易造成OOM n ...

  4. 2FA双因素认证 - 原理和应用

    主页 个人微信公众号:密码应用技术实战 个人博客园首页:https://www.cnblogs.com/informatics/ 引言 我们在登陆网站.或者通过VPN访问公司内网时,除了输入用户口令外 ...

  5. Github无法读取远程仓库

    主页 个人微信公众号:密码应用技术实战 个人博客园首页:https://www.cnblogs.com/informatics/ Git无法访问 今早起来访问Github炸了,Git不能用了,提示: ...

  6. jsPlumb导航器

    开源项目地址:https://gitee.com/easyxaf/jsplumb-navigator 前言 jsPlumb可用于连接DOM元素,它不依赖框架,所以与主流框架都可以无缝的集成.但比较遗憾 ...

  7. 音频wav文件转sbc工具wav2sbc下载

    前记: 书到用时方恨少,工具用时方才发现好不到.为了一个工具,也是折腾了有一阵了. 工具说明: 在耳机中,各大芯片公司为了节省内存,本地播放的一般都是sbc格式文件,这就用到了wav转sbc文件的软件 ...

  8. day03-1-查看账单&结账功能

    满汉楼03 4.功能实现05 4.8查看账单功能 按照之间搭建起来的框架,在BillService编写方法 4.8.1代码实现 1.修改Bill类 重写Bill类中的toString方法 @Overr ...

  9. python学习笔记(3):模块

    模块 一个.py文件就是一个模块,模块可以包含在包(package)内.包内必须有一个__init**__**.py,包也可以多层嵌套.__init__.py也是一个模块,模块名就是包名. 当用命令行 ...

  10. android使用StringRequest访问网站接收JSON时空指针报错

    報錯詳情: 代碼詳情: 报错原因:他丫变量名与JSON格式中的变量名不同