nasm : test bit

来源:互联网 发布:电脑时间校对软件 编辑:程序博客网 时间:2024/05/17 01:51

验证汇编指令

bt : 取指定的位到CF标志

setc : 设置CF到字节


nasm代码:

; @file ex1-1.asm; @brief <<nasm : test bit>>;测试计算机内容是小端序还是大端序排放, 用位测试的方法; @note 编译命令行 ; cd D:\prj\nasm_prj\boot\boot_dispmsg\ex1-1; d:; C:\nasm\nasm.exe ex1-1-test-bit.asm -o ex1-1-test-bit.bin -l ex1-1-test-bit.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加载后的位置; --------------------------------------------------------------------------------; 本模块入口点 offset 0; --------------------------------------------------------------------------------; /// 这句没用的, 自己用WinHex烧到想要的扇区org BOOT_CODE_ENTRY_POINT ; 程序加载到0x7c00; /// 0#扇区是 在 UltraISO 中格式化U盘(非快速格式化)后,按照USB-HDD方式写入的MBR; /// 0#扇区的MBR已经做了初始处理, 我们在实验中,只需要关心具体的逻辑即可; /// 清屏 call clear_screen; --------------------------------------------------------------------------------; 汇编指令的测试 : 位操作指令; --------------------------------------------------------------------------------mov word[byte_test], 2bt word[byte_test], 1 ; ///< test bit 1 to eflags CFsetc bl ; ///< set CF to byteadd bl, 0 ; ///< change ZF flagjnz 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:; --------------------------------------------------------------------------------; 定位光标到(0,1); --------------------------------------------------------------------------------push 0push 1call set_cursoradd sp, 4 ; ///< 堆栈平衡call disp_message_by_default_attributes; --------------------------------------------------------------------------------; 定位光标到(1,1); --------------------------------------------------------------------------------push 1push 1call set_cursoradd 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, 0disp_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, spadd ax, 4mov 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_cursorget_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, 0x5678str_tip_little_endian: db "this computer is little-endian", 0len_str_tip_little_endian equ ($ - str_tip_little_endian)str_tip_big_endian: db "this computer is big-endian", 0len_str_tip_big_endian equ ($ - str_tip_big_endian); /// 将工程信息写入编译后的文件, 可以在调试时,确认代码版本控制信息; /// 版本信息的前3位是发布时,面对用户的信息,最后一位是svn号码str_source_code_version: db "0.0.1.1", 0str_source_code_modify_time: db "2015_0925_0951", 0times 510-($-$$) db 0 ; 用0填充剩余空间,使该段二进制代码正好为512字节dw 0aa55h ; 结束标记



0 0