nasm : test eflags ZF
看看如何在bochs中查看标志寄存器,当标志寄存器置位和清零0,都是什么样子.
查看eflags的bochs命令 : info eflags
当(0 === ZF)时, ZF标志显示为zf
当(1 == ZF)时,ZF标志显示为ZF
其他标志位也是这样显示.
Next at t=156867343
(0) [0x000000007c39] 0000:7c39 (unk. ctxt): test byte ptr ds:0x7cf7, 0x00 ; f606f77c00
<bochs:13> info eflags
id vip vif ac vm rf nt IOPL=0 of df if tf sf zf AF PF cf
<bochs:14> s
Next at t=156867344
(0) [0x000000007c3e] 0000:7c3e (unk. ctxt): jz .+8 (0x00007c48) ; 7408
<bochs:15> info eflags
id vip vif ac vm rf nt IOPL=0 of df if tf sf ZF af PF cf
显示物理地址内容的 bochs命令 xp /nuf addr, 示例如下
<bochs:4> xp /10bx 0x7cf7
[bochs]:
0x0000000000007cf7 <bogus+ 0>: 0x00 0x7a 0x66 0x20 0x3d 0x3d 0x20 0x30
0x0000000000007cff <bogus+ 8>: 0x00 0x7a
第2个参数的含义 10 = 10个显示单位; b = 显示单位为字节; x = 显示为16进制数.
0#扇区为U盘的MBR
实验扇区为1#扇区
nasm 实验代码如下:
; @file ex1-1.asm
; @brief 测试计算机内容是小端序还是大端序排放
; @note 编译命令行
; cd D:\prj\nasm_prj\boot\boot_dispmsg\ex1-1
; d:
; C:\nasm\nasm.exe ex1-1.asm -o ex1-1.bin -l ex1-1.list
; @note 将ex1-1.bin写U盘1#扇区; 颜色
%define COLOR_BG_RED_FG_WHITE 47h ; ///< 红底白字; 函数内临时变量 - 以函数入口处的bp为基准
;Stack address size 2
; | STACK 0xffc6 [0x7ce7] ///< 函数内临时变量2
; | STACK 0xffc8 [0x0000] ///< 函数内临时变量1
; | STACK 0xffca [0xffcc] ///< 入口处的sp值
; | STACK 0xffcc [0x0000] ///< 入口处的bp值
; | STACK 0xffce [0x7c1e] ///< 函数返回地址, 入口处的bp值已经指到了这里%define FUNCTION_TEMP_VAR_1 [bp - 6]
%define FUNCTION_TEMP_VAR_2 [bp - 8]
%define FUNCTION_TEMP_VAR_3 [bp - 12]
%define FUNCTION_TEMP_VAR_4 [bp - 14]
%define FUNCTION_TEMP_VAR_5 [bp - 16]
%define FUNCTION_TEMP_VAR_6 [bp - 18]
%define FUNCTION_TEMP_VAR_7 [bp - 20]
%define FUNCTION_TEMP_VAR_8 [bp - 22]
%define FUNCTION_TEMP_VAR_9 [bp - 24]; 栈入参 - 以函数入口处的bp为基准
%define STACK_IN_PARAM_1 [bp + 2]
%define STACK_IN_PARAM_2 [bp + 4]
%define STACK_IN_PARAM_3 [bp + 6]
%define STACK_IN_PARAM_4 [bp + 8]
%define STACK_IN_PARAM_5 [bp + 10]
%define STACK_IN_PARAM_6 [bp + 12]
%define STACK_IN_PARAM_7 [bp + 14]
%define STACK_IN_PARAM_8 [bp + 16]
%define STACK_IN_PARAM_9 [bp + 18]; 栈出参 - 以函数入口处的sp为基准, 函数出口处的sp必须和入口处相同
; 必须先执行 mov si, sp 因为没有 mov ax, [sp + 4] 这样的指令
; 用完 STACK_OUT_PARAM_X 之后, 执行 pop bp
%define STACK_OUT_PARAM_1 [si + 0]
%define STACK_OUT_PARAM_2 [si + 2]
%define STACK_OUT_PARAM_3 [si + 4]
%define STACK_OUT_PARAM_4 [si + 6]
%define STACK_OUT_PARAM_5 [si + 8]
%define STACK_OUT_PARAM_6 [si + 10]
%define STACK_OUT_PARAM_7 [si + 12]
%define STACK_OUT_PARAM_8 [si + 14]
%define STACK_OUT_PARAM_9 [si + 16]%define BOOT_CODE_ENTRY_POINT 07c00h ; ///< boot 代码被BIOS加载后的位置; /// 这句没用的, 自己用WinHex烧到想要的扇区org BOOT_CODE_ENTRY_POINT ; 程序加载到0x7c00; /// 0#扇区是 在 UltraISO 中格式化U盘(非快速格式化)后,按照USB-HDD方式写入的MBR; /// 0#扇区的MBR已经做了初始处理, 我们在实验中,只需要关心具体的逻辑即可; /// 清屏call clear_screen; --------------------------------------------------------------------------------; 在(0,1)显示信息; --------------------------------------------------------------------------------push 0push 1call set_cursoradd sp, 4 ; ///< 堆栈平衡; /// 向内存地址中写内容,测试内存排放规则是大端序还是小端序; /// mov dword[byte_test], 1 ; ///< 只要向byte以上的空间写1,就可以看出内存排放规则mov word[byte_test], 1test byte[byte_test], 1jnz little_endianbig_endian:mov si, str_tip_big_endian mov cx, len_str_tip_big_endianjmp show_endianlittle_endian:mov si, str_tip_little_endian mov cx, len_str_tip_little_endianshow_endian:call disp_message_by_default_attributes; --------------------------------------------------------------------------------; 在(1,1)显示信息; --------------------------------------------------------------------------------push 1push 1call set_cursoradd sp, 4 ; ///< 堆栈平衡; /// 测试位是0还是1, 向看下当 jz时 info eflags 显示的 z位和 jnz时, 有何不同mov byte[byte_test], 0test byte[byte_test], 0jz z_flagnz_flag:mov si, str_zf_is_not_0mov cx, len_str_zf_is_not_0jmp show_z_flagz_flag:mov si, str_zf_is_0 mov cx, len_str_zf_is_0show_z_flag:call disp_message_by_default_attributes; --------------------------------------------------------------------------------; 在(2,1)显示信息; --------------------------------------------------------------------------------push 2push 1call set_cursoradd sp, 4 ; ///< 堆栈平衡; --------------------------------------------------------------------------------; /// @todo ls for debug; --------------------------------------------------------------------------------jmp $ ; 死循环; /// @fn disp_n_char_by_default_attributes(char* pcMsg, int iLenMsg)
; si = pcMsg
; cx = iLenMsgdisp_message_by_default_attributes:; /// 保护现场 bp和sppush bppush sp; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, axpush cx ; ///< 重复执行次数push bxmov bx, 0
disp_message_by_default_attributes_begin: cmp cx, 0jbe disp_message_by_default_attributes_end ; ///< 执行次数 <= 0, breakdec cxmov ax, [si + bx] ; ///< 需要显示的字符inc bxpush ax; /// disp_one_char_by_default_attributes 必须保护 bx,cx,sicall disp_one_char_by_default_attributesadd sp, 2 ; ///< 堆栈平衡jmp disp_message_by_default_attributes_begindisp_message_by_default_attributes_end:pop bxpop cx; /// 恢复现场 bp和sppop sppop bpret; /// @fn disp_one_char_by_default_attributes(char cDispContent)
disp_one_char_by_default_attributes: ; /// 保护现场 bp和sppush bppush sp; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, axpush bxpush cxpush sixor bh, bhmov ax, STACK_IN_PARAM_1mov ah, 0x0eint 0x10 pop sipop cxpop bx; /// 恢复现场 bp和sppop sppop bpret; /// 清屏
clear_screen:; /// 保护现场 bp和spmov ax, bppush axmov ax, sppush ax; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, ax; (7)、功能 06H 和 07H
; 功能描述:初始化屏幕或滚屏
; 入口参数:AH=06H——向上滚屏,07H——向下滚屏
; AL=滚动行数(0——清窗口)
; BH=空白区域的缺省属性
; (CH、CL)=窗口的左上角位置(Y 坐标,X 坐标)
; (DH、DL)=窗口的右下角位置(Y 坐标,X 坐标)
; 出口参数:无mov ah, 6hmov al, 0mov bh, 17h ; ///< 蓝底白字,光标闪烁mov cl, 0mov ch, 0mov dl, 79mov dh, 24int 10h; --------------------------------------------------------------------------------; /// @todo ls for debug; --------------------------------------------------------------------------------
; jmp $ ; 死循环; /// 恢复现场 bp和sppop sppop bpret; /// 设置光标位置
; /// set_cursor(x, y)
set_cursor:; /// 保护现场 bp和sppush bppush sp; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, ax; push CURSOR_Y_0 ; ///< STACK_PARAM2; push CURSOR_X_0 ; ///< STACK_PARAM1mov ax, 0mov bh, al ; ///< display page numbermov ax, STACK_IN_PARAM_1mov dl, al ; ///< cursor column, CURSOR_X_Nmov ax, STACK_IN_PARAM_2mov dh, al ; ///< cursor row, CURSOR_Y_Nmov ah, 2mov al, 0int 10h; /// 恢复现场 bp和sppop sppop bpret ; /// 得到光标位置
; /// get_cursor(x, y)
; 调用示例
; push 0 ///< y, STACK_OUT_PARAM_2
; push 0 ///< x, STACK_OUT_PARAM_1
; call get_cursorget_cursor:; /// 保护现场 bp和sppush bppush sp; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, ax; push CURSOR_Y_0 ; ///< STACK_PARAM2; push CURSOR_X_0 ; ///< STACK_PARAM1; (4)、功能 03H
; 功能描述:在文本坐标下,读取光标各种信息
; 入口参数:AH=03H
; BH=显示页码
; 出口参数:CH=光标的起始行
; CL=光标的终止行
; DH=行(Y 坐标)
; DL=列(X 坐标)xor ax, axmov ah, 3hmov bh, 0int 10hmov ax, dxmov STACK_IN_PARAM_1, ax; /// 恢复现场 bp和sppop sppop bpret byte_test dw 0x1234, 0x5678str_zf_is_0: db "zf == 0", 0
len_str_zf_is_0 equ ($ - str_zf_is_0)str_zf_is_not_0: db "zf != 0", 0
len_str_zf_is_not_0 equ ($ - str_zf_is_not_0)str_tip_little_endian: db "this computer is little-endian", 0
len_str_tip_little_endian equ ($ - str_tip_little_endian)str_tip_big_endian: db "this computer is big-endian", 0
len_str_tip_big_endian equ ($ - str_tip_big_endian)str_build_time: db "2015_0924_1120"times 510-($-$$) db 0 ; 用0填充剩余空间,使该段二进制代码正好为512字节
dw 0aa55h ; 结束标记
; @file ex1-1.asm
; @brief 测试计算机内容是小端序还是大端序排放
; @note 编译命令行
; cd D:\prj\nasm_prj\boot\boot_dispmsg\ex1-1
; d:
; C:\nasm\nasm.exe ex1-1.asm -o ex1-1.bin -l ex1-1.list
; @note 将ex1-1.bin写U盘1#扇区; 颜色
%define COLOR_BG_RED_FG_WHITE 47h ; ///< 红底白字; 函数内临时变量 - 以函数入口处的bp为基准
;Stack address size 2
; | STACK 0xffc6 [0x7ce7] ///< 函数内临时变量2
; | STACK 0xffc8 [0x0000] ///< 函数内临时变量1
; | STACK 0xffca [0xffcc] ///< 入口处的sp值
; | STACK 0xffcc [0x0000] ///< 入口处的bp值
; | STACK 0xffce [0x7c1e] ///< 函数返回地址, 入口处的bp值已经指到了这里%define FUNCTION_TEMP_VAR_1 [bp - 6]
%define FUNCTION_TEMP_VAR_2 [bp - 8]
%define FUNCTION_TEMP_VAR_3 [bp - 12]
%define FUNCTION_TEMP_VAR_4 [bp - 14]
%define FUNCTION_TEMP_VAR_5 [bp - 16]
%define FUNCTION_TEMP_VAR_6 [bp - 18]
%define FUNCTION_TEMP_VAR_7 [bp - 20]
%define FUNCTION_TEMP_VAR_8 [bp - 22]
%define FUNCTION_TEMP_VAR_9 [bp - 24]; 栈入参 - 以函数入口处的bp为基准
%define STACK_IN_PARAM_1 [bp + 2]
%define STACK_IN_PARAM_2 [bp + 4]
%define STACK_IN_PARAM_3 [bp + 6]
%define STACK_IN_PARAM_4 [bp + 8]
%define STACK_IN_PARAM_5 [bp + 10]
%define STACK_IN_PARAM_6 [bp + 12]
%define STACK_IN_PARAM_7 [bp + 14]
%define STACK_IN_PARAM_8 [bp + 16]
%define STACK_IN_PARAM_9 [bp + 18]; 栈出参 - 以函数入口处的sp为基准, 函数出口处的sp必须和入口处相同
; 必须先执行 mov si, sp 因为没有 mov ax, [sp + 4] 这样的指令
; 用完 STACK_OUT_PARAM_X 之后, 执行 pop bp
%define STACK_OUT_PARAM_1 [si + 0]
%define STACK_OUT_PARAM_2 [si + 2]
%define STACK_OUT_PARAM_3 [si + 4]
%define STACK_OUT_PARAM_4 [si + 6]
%define STACK_OUT_PARAM_5 [si + 8]
%define STACK_OUT_PARAM_6 [si + 10]
%define STACK_OUT_PARAM_7 [si + 12]
%define STACK_OUT_PARAM_8 [si + 14]
%define STACK_OUT_PARAM_9 [si + 16]%define BOOT_CODE_ENTRY_POINT 07c00h ; ///< boot 代码被BIOS加载后的位置; /// 这句没用的, 自己用WinHex烧到想要的扇区org BOOT_CODE_ENTRY_POINT ; 程序加载到0x7c00; /// 0#扇区是 在 UltraISO 中格式化U盘(非快速格式化)后,按照USB-HDD方式写入的MBR; /// 0#扇区的MBR已经做了初始处理, 我们在实验中,只需要关心具体的逻辑即可; /// 清屏call clear_screen; --------------------------------------------------------------------------------; 在(0,1)显示信息; --------------------------------------------------------------------------------push 0push 1call set_cursoradd sp, 4 ; ///< 堆栈平衡; /// 向内存地址中写内容,测试内存排放规则是大端序还是小端序mov dword[byte_test], 1test byte[byte_test], 1jnz little_endianbig_endian:mov si, str_tip_big_endian mov cx, len_str_tip_big_endianjmp show_endianlittle_endian:mov si, str_tip_little_endian mov cx, len_str_tip_little_endianshow_endian:call disp_message_by_default_attributes; --------------------------------------------------------------------------------; 在(1,1)显示信息; --------------------------------------------------------------------------------push 1push 1call set_cursoradd sp, 4 ; ///< 堆栈平衡; /// 测试位是0还是1, 向看下当 jz时 info eflags 显示的 z位和 jnz时, 有何不同mov byte[byte_test], 0test byte[byte_test], 0jz z_flagnz_flag:mov si, str_zf_is_not_0mov cx, len_str_zf_is_not_0jmp show_z_flagz_flag:mov si, str_zf_is_0 mov cx, len_str_zf_is_0show_z_flag:call disp_message_by_default_attributes; --------------------------------------------------------------------------------; 在(2,1)显示信息; --------------------------------------------------------------------------------push 2push 1call set_cursoradd sp, 4 ; ///< 堆栈平衡; --------------------------------------------------------------------------------; /// @todo ls for debug; --------------------------------------------------------------------------------jmp $ ; 死循环; /// @fn disp_n_char_by_default_attributes(char* pcMsg, int iLenMsg)
; si = pcMsg
; cx = iLenMsgdisp_message_by_default_attributes:; /// 保护现场 bp和sppush bppush sp; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, axpush cx ; ///< 重复执行次数push bxmov bx, 0
disp_message_by_default_attributes_begin: cmp cx, 0jbe disp_message_by_default_attributes_end ; ///< 执行次数 <= 0, breakdec cxmov ax, [si + bx] ; ///< 需要显示的字符inc bxpush ax; /// disp_one_char_by_default_attributes 必须保护 bx,cx,sicall disp_one_char_by_default_attributesadd sp, 2 ; ///< 堆栈平衡jmp disp_message_by_default_attributes_begindisp_message_by_default_attributes_end:pop bxpop cx; /// 恢复现场 bp和sppop sppop bpret; /// @fn disp_one_char_by_default_attributes(char cDispContent)
disp_one_char_by_default_attributes: ; /// 保护现场 bp和sppush bppush sp; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, axpush bxpush cxpush sixor bh, bhmov ax, STACK_IN_PARAM_1mov ah, 0x0eint 0x10 pop sipop cxpop bx; /// 恢复现场 bp和sppop sppop bpret; /// 清屏
clear_screen:; /// 保护现场 bp和spmov ax, bppush axmov ax, sppush ax; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, ax; (7)、功能 06H 和 07H
; 功能描述:初始化屏幕或滚屏
; 入口参数:AH=06H——向上滚屏,07H——向下滚屏
; AL=滚动行数(0——清窗口)
; BH=空白区域的缺省属性
; (CH、CL)=窗口的左上角位置(Y 坐标,X 坐标)
; (DH、DL)=窗口的右下角位置(Y 坐标,X 坐标)
; 出口参数:无mov ah, 6hmov al, 0mov bh, 17h ; ///< 蓝底白字,光标闪烁mov cl, 0mov ch, 0mov dl, 79mov dh, 24int 10h; --------------------------------------------------------------------------------; /// @todo ls for debug; --------------------------------------------------------------------------------
; jmp $ ; 死循环; /// 恢复现场 bp和sppop sppop bpret; /// 设置光标位置
; /// set_cursor(x, y)
set_cursor:; /// 保护现场 bp和sppush bppush sp; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, ax; push CURSOR_Y_0 ; ///< STACK_PARAM2; push CURSOR_X_0 ; ///< STACK_PARAM1mov ax, 0mov bh, al ; ///< display page numbermov ax, STACK_IN_PARAM_1mov dl, al ; ///< cursor column, CURSOR_X_Nmov ax, STACK_IN_PARAM_2mov dh, al ; ///< cursor row, CURSOR_Y_Nmov ah, 2mov al, 0int 10h; /// 恢复现场 bp和sppop sppop bpret ; /// 得到光标位置
; /// get_cursor(x, y)
; 调用示例
; push 0 ///< y, STACK_OUT_PARAM_2
; push 0 ///< x, STACK_OUT_PARAM_1
; call get_cursorget_cursor:; /// 保护现场 bp和sppush bppush sp; /// 使bp回到函数入口处的值mov ax, spadd ax, 4mov bp, ax; push CURSOR_Y_0 ; ///< STACK_PARAM2; push CURSOR_X_0 ; ///< STACK_PARAM1; (4)、功能 03H
; 功能描述:在文本坐标下,读取光标各种信息
; 入口参数:AH=03H
; BH=显示页码
; 出口参数:CH=光标的起始行
; CL=光标的终止行
; DH=行(Y 坐标)
; DL=列(X 坐标)xor ax, axmov ah, 3hmov bh, 0int 10hmov ax, dxmov STACK_IN_PARAM_1, ax; /// 恢复现场 bp和sppop sppop bpret byte_test dw 0x1234, 0x5678str_zf_is_0: db "zf == 0", 0
len_str_zf_is_0 equ ($ - str_zf_is_0)str_zf_is_not_0: db "zf != 0", 0
len_str_zf_is_not_0 equ ($ - str_zf_is_not_0)str_tip_little_endian: db "this computer is little-endian", 0
len_str_tip_little_endian equ ($ - str_tip_little_endian)str_tip_big_endian: db "this computer is big-endian", 0
len_str_tip_big_endian equ ($ - str_tip_big_endian)str_build_time: db "2015_0924_1120"times 510-($-$$) db 0 ; 用0填充剩余空间,使该段二进制代码正好为512字节
dw 0aa55h ; 结束标记
nasm : test eflags ZF相关推荐
- X87 FPU 指令集
FPU 指令集 (1) FPU 数据传输指令集 fld 将浮点值压入寄存器栈,源操作数可以是ST(i)或内存地址 fild 从内存中读取一个有符号整型操作数,将该值转换为扩展双精度值,并将此结果加载到 ...
- x86-SSE指令集
SSE 指令集 (1)SSE 标量浮点数据传输指令 movss movsd 在俩个xmm指令金阊区之间或者内存位置和xmm寄存器之间复制标量浮点数 (2)SSE 标量浮点算术运算指令 addss ad ...
- PA2.1 运行dumy
PA2.1实现dumy 实现思路 实验过程 修改opcode_table数组 修改rtl.h文件 实现对应的操作 实验结果 实现思路 在进行代码编写之前,最重要的就是阅读实验手册,确保自己真的理解了实 ...
- 状态标志寄存器--EFLAGS
EFLAGS寄存器有控制CPU的操作或反映CPU某些运算的结果的独立二进制位构成. 标志位 名称 全称 作用 CF 进位标志 Carry Flag 无符号算术运算的结果太大而目的操作数无法容纳时置位 ...
- Ubuntu下用gcc与nasm联合编译
1.代码 foo.asm [plain] view plaincopy ;编译链接的方法 ;(id的'-s'选项意为"strip all") ; ;$ nasm -f elf fo ...
- RTEMS实时操作系统精要(2)-FLAGS、EFLAGS寄存器
FLAGS寄存器是Intel x86微处理器中的状态寄存器,它包含处理器的当前状态.这个寄存器是16位宽的.它的后继者EFLAGS和RFLAGS寄存器的宽度分别为32位和64位.较宽的寄存器保持了与较 ...
- 跟着锅子一步步学习32位汇编(4)---EFLAGS及标志位操作指令
先看图 园子里找的图,再附上理论,具体操作等以后慢慢讲. 标志寄存器用来保存在一条指令执行完成后,CPU所处状态的信息及运算结果的特征. 16位标志寄存器 FLAGS 32位标志寄存器 EFLAGS ...
- 操作系统真象还原第1.5章 NASM汇编学习
第二章有使用 NASM 汇编写主引导记录 MBR 的内容. 在写第二章的代码前,每天晚上下班后花一些时间简单地回顾了 NASM 汇编的内容,只复习了最简单的语法,之后写 OS 时再边写边查资料. 指令 ...
- NASM: Register 寄存器
NASM: Register 寄存器 文章目录 NASM: Register 寄存器 简介 参考 正文 寄存器分类 数据寄存器:`AX`.`BX`.`CX`.`DX` 高位 H 和低位 L:`AH`. ...
最新文章
- 神经进化:一种不一样的深度学习
- CI类实现session基本用法
- 【Linux入门到精通系列讲解】Nginx详细介绍和安装使用(这一篇就够了)
- Android application捕获崩溃异常
- python进程、线程的学习心得
- VTK:Qt之ImageDataToQImage
- jquery 图像滑块_10个很棒的jQuery图像滑块插件
- 截取网页中的Flash
- 操作系统清华 向勇 陈渝(RISC-V)(2)---操作系统与系统结构和程序设计语言
- 135编辑器代码是html吗,不会代码,你也能做背景样式!!!
- Hyperledger/FireFly
- lol服务器显示40ms,一个简单insert 语句执行 40ms 原因剖析
- 第八章 性能优化 之 内存优化(一)
- 未来必将是AI的天下
- 语音备忘录里的录音怎么导出来
- 本地ecshop网站怎么上传到服务器,ecshop 上传服务器
- 苹果新功能惹众怒,4000多家组织和个人签署公开信 敦促苹果放弃“儿童安全”功能
- Mixly21:遥控彩灯
- Arduino使用SK6812(WS2812) 全彩RGB模块/ArduinoC、Mixly/Scartch
- Object类是什么?