nasm : test eflags ZF
2015-09-24 12:42
316 查看
看看如何在bochs中查看标志寄存器,当标志寄存器置位和清零0,都是什么样子.
查看eflags的bochs命令 : info eflags
当(0 === ZF)时, ZF标志显示为zf
当(1 == ZF)时,ZF标志显示为ZF
其他标志位也是这样显示.
显示物理地址内容的 bochs命令 xp /nuf addr, 示例如下
第2个参数的含义 10 = 10个显示单位; b = 显示单位为字节; x = 显示为16进制数.
0#扇区为U盘的MBR
实验扇区为1#扇区
nasm 实验代码如下:
查看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 0 push 1 call set_cursor add sp, 4 ; ///< 堆栈平衡 ; /// 向内存地址中写内容,测试内存排放规则是大端序还是小端序 ; /// mov dword[byte_test], 1 ; ///< 只要向byte以上的空间写1,就可以看出内存排放规则 mov word[byte_test], 1 test byte[byte_test], 1 jnz little_endian big_endian: mov si, str_tip_big_endian mov cx, len_str_tip_big_endian jmp show_endian little_endian: mov si, str_tip_little_endian mov cx, len_str_tip_little_endian show_endian: call disp_message_by_default_attributes ; -------------------------------------------------------------------------------- ; 在(1,1)显示信息 ; -------------------------------------------------------------------------------- push 1 push 1 call set_cursor add sp, 4 ; ///< 堆栈平衡 ; /// 测试位是0还是1, 向看下当 jz时 info eflags 显示的 z位和 jnz时, 有何不同 mov byte[byte_test], 0 test byte[byte_test], 0 jz z_flag nz_flag: mov si, str_zf_is_not_0 mov cx, len_str_zf_is_not_0 jmp show_z_flag z_flag: mov si, str_zf_is_0 mov cx, len_str_zf_is_0 show_z_flag: call disp_message_by_default_attributes ; -------------------------------------------------------------------------------- ; 在(2,1)显示信息 ; -------------------------------------------------------------------------------- push 2 push 1 call set_cursor add sp, 4 ; ///< 堆栈平衡 ; -------------------------------------------------------------------------------- ; /// @todo ls for debug ; -------------------------------------------------------------------------------- jmp $ ; 死循环 ; /// @fn disp_n_char_by_default_attributes(char* pcMsg, int iLenMsg) ; si = pcMsg ; cx = iLenMsg disp_message_by_default_attributes: ; /// 保护现场 bp和sp push bp push sp ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov bp, ax push cx ; ///< 重复执行次数 push bx mov bx, 0 disp_message_by_default_attributes_begin: cmp cx, 0 jbe disp_message_by_default_attributes_end ; ///< 执行次数 <= 0, break dec cx mov ax, [si + bx] ; ///< 需要显示的字符 inc bx push ax ; /// disp_one_char_by_default_attributes 必须保护 bx,cx,si call disp_one_char_by_default_attributes add sp, 2 ; ///< 堆栈平衡 jmp disp_message_by_default_attributes_begin disp_message_by_default_attributes_end: pop bx pop cx ; /// 恢复现场 bp和sp pop sp pop bp ret ; /// @fn disp_one_char_by_default_attributes(char cDispContent) disp_one_char_by_default_attributes: ; /// 保护现场 bp和sp push bp push sp ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov bp, ax push bx push cx push si xor bh, bh mov ax, STACK_IN_PARAM_1 mov ah, 0x0e int 0x10 pop si pop cx pop bx ; /// 恢复现场 bp和sp pop sp pop bp ret ; /// 清屏 clear_screen: ; /// 保护现场 bp和sp mov ax, bp push ax mov ax, sp push ax ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov bp, ax ; (7)、功能 06H 和 07H ; 功能描述:初始化屏幕或滚屏 ; 入口参数:AH=06H——向上滚屏,07H——向下滚屏 ; AL=滚动行数(0——清窗口) ; BH=空白区域的缺省属性 ; (CH、CL)=窗口的左上角位置(Y 坐标,X 坐标) ; (DH、DL)=窗口的右下角位置(Y 坐标,X 坐标) ; 出口参数:无 mov ah, 6h mov al, 0 mov bh, 17h ; ///< 蓝底白字,光标闪烁 mov cl, 0 mov ch, 0 mov dl, 79 mov dh, 24 int 10h ; -------------------------------------------------------------------------------- ; /// @todo ls for debug ; -------------------------------------------------------------------------------- ; jmp $ ; 死循环 ; /// 恢复现场 bp和sp pop sp pop bp ret ; /// 设置光标位置 ; /// set_cursor(x, y) set_cursor: ; /// 保护现场 bp和sp push bp push sp ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov bp, ax ; push CURSOR_Y_0 ; ///< STACK_PARAM2 ; push CURSOR_X_0 ; ///< STACK_PARAM1 mov ax, 0 mov bh, al ; ///< display page number mov ax, STACK_IN_PARAM_1 mov dl, al ; ///< cursor column, CURSOR_X_N mov ax, STACK_IN_PARAM_2 mov dh, al ; ///< cursor row, CURSOR_Y_N mov ah, 2 mov al, 0 int 10h ; /// 恢复现场 bp和sp pop sp pop bp ret ; /// 得到光标位置 ; /// get_cursor(x, y) ; 调用示例 ; push 0 ///< y, STACK_OUT_PARAM_2 ; push 0 ///< x, STACK_OUT_PARAM_1 ; call get_cursor get_cursor: ; /// 保护现场 bp和sp push bp push sp ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov 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, ax mov ah, 3h mov bh, 0 int 10h mov ax, dx mov STACK_IN_PARAM_1, ax ; /// 恢复现场 bp和sp pop sp pop bp ret byte_test dw 0x1234, 0x5678 str_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 0 push 1 call set_cursor add sp, 4 ; ///< 堆栈平衡 ; /// 向内存地址中写内容,测试内存排放规则是大端序还是小端序 mov dword[byte_test], 1 test byte[byte_test], 1 jnz little_endian big_endian: mov si, str_tip_big_endian mov cx, len_str_tip_big_endian jmp show_endian little_endian: mov si, str_tip_little_endian mov cx, len_str_tip_little_endian show_endian: call disp_message_by_default_attributes ; -------------------------------------------------------------------------------- ; 在(1,1)显示信息 ; -------------------------------------------------------------------------------- push 1 push 1 call set_cursor add sp, 4 ; ///< 堆栈平衡 ; /// 测试位是0还是1, 向看下当 jz时 info eflags 显示的 z位和 jnz时, 有何不同 mov byte[byte_test], 0 test byte[byte_test], 0 jz z_flag nz_flag: mov si, str_zf_is_not_0 mov cx, len_str_zf_is_not_0 jmp show_z_flag z_flag: mov si, str_zf_is_0 mov cx, len_str_zf_is_0 show_z_flag: call disp_message_by_default_attributes ; -------------------------------------------------------------------------------- ; 在(2,1)显示信息 ; -------------------------------------------------------------------------------- push 2 push 1 call set_cursor add sp, 4 ; ///< 堆栈平衡 ; -------------------------------------------------------------------------------- ; /// @todo ls for debug ; -------------------------------------------------------------------------------- jmp $ ; 死循环 ; /// @fn disp_n_char_by_default_attributes(char* pcMsg, int iLenMsg) ; si = pcMsg ; cx = iLenMsg disp_message_by_default_attributes: ; /// 保护现场 bp和sp push bp push sp ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov bp, ax push cx ; ///< 重复执行次数 push bx mov bx, 0 disp_message_by_default_attributes_begin: cmp cx, 0 jbe disp_message_by_default_attributes_end ; ///< 执行次数 <= 0, break dec cx mov ax, [si + bx] ; ///< 需要显示的字符 inc bx push ax ; /// disp_one_char_by_default_attributes 必须保护 bx,cx,si call disp_one_char_by_default_attributes add sp, 2 ; ///< 堆栈平衡 jmp disp_message_by_default_attributes_begin disp_message_by_default_attributes_end: pop bx pop cx ; /// 恢复现场 bp和sp pop sp pop bp ret ; /// @fn disp_one_char_by_default_attributes(char cDispContent) disp_one_char_by_default_attributes: ; /// 保护现场 bp和sp push bp push sp ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov bp, ax push bx push cx push si xor bh, bh mov ax, STACK_IN_PARAM_1 mov ah, 0x0e int 0x10 pop si pop cx pop bx ; /// 恢复现场 bp和sp pop sp pop bp ret ; /// 清屏 clear_screen: ; /// 保护现场 bp和sp mov ax, bp push ax mov ax, sp push ax ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov bp, ax ; (7)、功能 06H 和 07H ; 功能描述:初始化屏幕或滚屏 ; 入口参数:AH=06H——向上滚屏,07H——向下滚屏 ; AL=滚动行数(0——清窗口) ; BH=空白区域的缺省属性 ; (CH、CL)=窗口的左上角位置(Y 坐标,X 坐标) ; (DH、DL)=窗口的右下角位置(Y 坐标,X 坐标) ; 出口参数:无 mov ah, 6h mov al, 0 mov bh, 17h ; ///< 蓝底白字,光标闪烁 mov cl, 0 mov ch, 0 mov dl, 79 mov dh, 24 int 10h ; -------------------------------------------------------------------------------- ; /// @todo ls for debug ; -------------------------------------------------------------------------------- ; jmp $ ; 死循环 ; /// 恢复现场 bp和sp pop sp pop bp ret ; /// 设置光标位置 ; /// set_cursor(x, y) set_cursor: ; /// 保护现场 bp和sp push bp push sp ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov bp, ax ; push CURSOR_Y_0 ; ///< STACK_PARAM2 ; push CURSOR_X_0 ; ///< STACK_PARAM1 mov ax, 0 mov bh, al ; ///< display page number mov ax, STACK_IN_PARAM_1 mov dl, al ; ///< cursor column, CURSOR_X_N mov ax, STACK_IN_PARAM_2 mov dh, al ; ///< cursor row, CURSOR_Y_N mov ah, 2 mov al, 0 int 10h ; /// 恢复现场 bp和sp pop sp pop bp ret ; /// 得到光标位置 ; /// get_cursor(x, y) ; 调用示例 ; push 0 ///< y, STACK_OUT_PARAM_2 ; push 0 ///< x, STACK_OUT_PARAM_1 ; call get_cursor get_cursor: ; /// 保护现场 bp和sp push bp push sp ; /// 使bp回到函数入口处的值 mov ax, sp add ax, 4 mov 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, ax mov ah, 3h mov bh, 0 int 10h mov ax, dx mov STACK_IN_PARAM_1, ax ; /// 恢复现场 bp和sp pop sp pop bp ret byte_test dw 0x1234, 0x5678 str_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 ; 结束标记
相关文章推荐
- NYOJ 161 取石子 (四)(威佐夫博奕)
- php二维数组用键名分组相加实例函数
- iOS 获取时间
- Java基础知识强化59:String(字符串)和其他类型的相互转化
- 两个div重叠
- AndroidPN任务机制
- 第二次作业(1.个人项目实践)
- UILabel UiButton 文字下面加下划线
- 在MAC上查找和设置$JAVA_HOME
- 设计模式六大原则(3):依赖倒置原则
- Java—数组添加元素
- 深入理解STL源码 系列文章
- Find
- java编写的九九乘法表小程序
- sqlserver 视图和sql语句的效率对比
- How to get the root permission of android
- sql 学习笔记 档
- C#获取客户端相关信息实例总结
- leetcode_Restore IP Addresses
- poj3449 多边形的相交问题,输入输出比较麻烦