nasm : 堆栈平衡的函数调用

来源:互联网 发布:mac mini 2014 换内存 编辑:程序博客网 时间:2024/05/02 00:40

更新 disp_char_repeat, 使写入的字符和背景不同

效果图:


; /// 重复显示字符disp_char_repeat:mov bp, sppush bp;(9)、功能 09H;功能描述:在当前光标处按指定属性显示字符;入口参数:AH=09H;AL=字符;BH=显示页码;BL=属性(文本模式)或颜色(图形模式);CX=重复输出字符的次数;出口参数:无;push PAGE_0 ; ///< STACK_PARAM_4;push COLOR_BG_READ_FG_WHITE ; ///< STACK_PARAM_3;push CHAR_TO_DISP ; ///< STACK_PARAM_2;push CHAR_COUNT ; ///< STACK_PARAM_1mov ax, STACK_PARAM_4mov bh, al ; no.0 page mov ax, STACK_PARAM_3mov bl, al ; char color, 红底白字mov ax, STACK_PARAM_1mov cx, ax ; char countmov ax, STACK_PARAM_2 ; char contentmov ah, 09h ; 在当前光标处按指定属性显示字符int 10hpop bpmov sp, bpret


<bk on 2015_0919_1226>

做实验时,发现有时执行的效果不科学。

开始直接烧到U盘0扇区,很麻烦。一直找不到错在哪.

后来用bochsdbg单步,很快发现了问题. 

* 参数传递时, [bp + 2]为栈中参数的开始

* 函数调用完,需要调用者进行堆栈平衡

bochs挺好用的, 调试利器. 写的很人性化,只要用过别的调试器,很快上手,命令不多,10几个. 命令字的助记符也很好记.

显示效果和裸机上相同.


; @file boot_disp_string_by_call.asm; @brief 启动后显示一些信息; @note 编译命令行 ; cd D:\prj\nasm_prj\boot\boot_dispmsg; d:; C:\nasm\nasm.exe -f bin -d UBOOT -l boot_disp_string_by_call.list boot_disp_string_by_call.asm -o boot_2015_0919_0833; @note 将boot_2015_0919_0833写U盘0扇区; @note 效果 : 显示一句话; /// 栈上的参数; /// 进入函数后,栈上保存的参数为: ; /// [sp + 0]返回地址; /// [sp + 2]参数1(左1); /// [sp + 4]参数2(左2); /// [sp + 6]参数3(左3); /// | STACK 0xffce [0x7c13]; /// | STACK 0xffd0 [0x0000]; /// | STACK 0xffd2 [0x0000]; /// | STACK 0xffd4 [0x0000]; /// 此时 sp 指向函数返回地址; /// 函数入口保存现场; /// mov bp, sp; /// push bp; /// 此时 bp 指向函数返回地址; /// 所以在函数中使用入参时, ; /// [bp + 0] 是函数返回地址; /// [bp + 2]参数1(左1); /// [bp + 4]参数2(左2); /// [bp + 8]参数3(左3) ...%define STACK_PARAM_1 [bp + 2]%define STACK_PARAM_2 [bp + 4] ; ///<  对于16位汇编, offset是2,而不是4%define STACK_PARAM_3 [bp + 6]%define STACK_PARAM_4 [bp + 8]%define STACK_PARAM_5 [bp + 10]%define STACK_PARAM_6 [bp + 12]%define STACK_PARAM_7 [bp + 14]%define STACK_PARAM_8 [bp + 16]%define STACK_PARAM_9 [bp + 18]%define PAGE_0 0 ; ///< 显存页0%define COLOR_BG_READ_FG_WHITE 47h ; ///< 红底白字%define CHAR_TO_DISP '=' ; ///< 要显示的字符内容%define CHAR_COUNT 40 ; ///< 字符个数, 通过实验, 果真能看到一行是80个字符%define CURSOR_X_0 0%define CURSOR_Y_0 0%define CURSOR_X_1 1%define CURSOR_Y_1 1%define CURSOR_X_2 2%define CURSOR_Y_2 2%define CURSOR_X_3 3%define CURSOR_Y_3 3%define CURSOR_X_4 4%define CURSOR_Y_4 4%define CURSOR_X_5 5%define CURSOR_Y_5 5org 0hmov ax, cxmov ds, axmov es, axcall clear_screen ; ///< 清屏nop; /// 将入参从右往左入栈; /// 在调试模式下,单步vs2010中编写的程序反汇编,是这样的; /// 设置光标到(0,0)push CURSOR_Y_0 ; ///< STACK_PARAM_3push CURSOR_X_0 ; ///< STACK_PARAM_2push PAGE_0 ; ///< STACK_PARAM_1call set_cursor ; ///< set_cursor(PAGE_0, CURSOR_X_1, CURSOR_Y_2)pop ax;///< 堆栈平衡pop axpop axcall print_line40; /// 设置光标到(1,1)push CURSOR_Y_1push CURSOR_X_1push PAGE_0call set_cursor ; ///< set_cursor(PAGE_0, CURSOR_X_1, CURSOR_Y_2)pop ax;///< 堆栈平衡pop axpop axcall print_line40; /// 设置光标到(2,2)push CURSOR_Y_2push CURSOR_X_2push PAGE_0call set_cursor ; ///< set_cursor(PAGE_0, CURSOR_X_1, CURSOR_Y_2)pop ax;///< 堆栈平衡pop axpop axcall print_line40; /// 设置光标到(3,3)push CURSOR_Y_3push CURSOR_X_3push PAGE_0call set_cursor ; ///< set_cursor(PAGE_0, CURSOR_X_1, CURSOR_Y_2)pop ax;///< 堆栈平衡pop axpop axcall print_line40; /// >>push CURSOR_Y_4push CURSOR_X_4push PAGE_0call set_cursor ; ///< set_cursor(PAGE_0, CURSOR_X_1, CURSOR_Y_2)pop ax;///< 堆栈平衡pop axpop axcall print_line40; /// >>jmp $ ; 死循环print_line40:mov bp, sppush bppush PAGE_0 ; ///< STACK_PARAM_1push COLOR_BG_READ_FG_WHITE ; ///< STACK_PARAM_2push CHAR_TO_DISP ; ///< STACK_PARAM_3push CHAR_COUNT ; ///< STACK_PARAM_4call disp_char_repeat ; 调用函数-显示字符串pop ax;///< 堆栈平衡pop axpop axpop axpop bpmov sp, bpret; /// 清屏clear_screen:mov bp, sppush bp;(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 10hpop bpmov sp, bpret; /// 设置光标位置set_cursor:mov bp, sppush bp;push CURSOR_Y_0 ; ///< STACK_PARAM_3;push CURSOR_X_0 ; ///< STACK_PARAM_2;push PAGE_0 ; ///< STACK_PARAM_1mov ax, STACK_PARAM_1mov bh, al ; ///< display page numbermov ax, STACK_PARAM_2mov dl, al ; ///< cursor column, CURSOR_X_Nmov ax, STACK_PARAM_3mov dh, al ; ///< cursor row, CURSOR_Y_Nmov ah, 2mov al, 0int 10hpop bpmov sp, bpret; /// 重复显示字符disp_char_repeat:mov bp, sppush bp;push PAGE_0 ; ///< STACK_PARAM_4;push COLOR_BG_READ_FG_WHITE ; ///< STACK_PARAM_3;push CHAR_TO_DISP ; ///< STACK_PARAM_2;push CHAR_COUNT ; ///< STACK_PARAM_1mov ax, STACK_PARAM_4mov bh, al ; no.0 page ; /// 按照原有的属性重复写字符, 这的颜色没用了mov ax, STACK_PARAM_3mov bl, al ; char color, 红底白字mov ax, STACK_PARAM_1mov cx, ax ; char countmov ax, STACK_PARAM_2 ; char contentmov ah, 0ah ; bios 10# function = write char to UIint 10hpop bpmov sp, bpret; /// 做个标记,在拷贝到U盘的前后,都可以确认是否为自己最新的修改str_build_time db 'build on 2015_0919_1003', 0len_str_build_time equ ($-str_build_time) ; ///< 串长度times 510-($-$$) db 0 ; 用0填充剩余空间,使该段二进制代码正好为512字节dw 0aa55h ; 结束标记



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 两岁宝宝口气重怎么办 两岁宝宝有口臭怎么办 两岁身高不达标怎么办 两岁宝宝82厘米怎么办 2岁幼儿说话结巴怎么办 2岁的宝宝结巴怎么办 2岁半宝宝口吃怎么办 2周岁宝宝不说话怎么办 三周岁宝宝不说话怎么办 2周岁宝宝突然说话结巴怎么办 两周岁宝宝突然说话结巴怎么办 三周岁宝宝说话突然结巴怎么办 小孩g和d不分怎么办 两岁宝宝皮肤黑怎么办 2岁宝宝肤色偏黄怎么办 2岁宝宝迷上手机怎么办 2岁宝宝说话口吃怎么办 两岁宝宝突然口吃怎么办 两岁半的宝宝还不会说话怎么办 2岁宝宝自闭症怎么办呀 新生儿又吐又拉怎么办 一岁多宝宝受凉呕吐拉稀怎么办 7个月的宝宝腹泻怎么办 两岁宝宝拉稀水怎么办 2岁宝宝发烧呕吐怎么办 1岁宝宝着凉呕吐怎么办 2岁着凉了呕吐怎么办 2岁宝宝着凉呕吐怎么办 两岁宝宝偏矮怎么办 2岁宝贝吐没精神怎么办 11个月的宝宝吐怎么办 二岁的宝宝吐了怎么办 十个月小孩吐了怎么办 10个月宝宝呕吐怎么办 小孩又拉又吐的怎么办 小孩子不吃饭呕吐拉肚子怎么办 小孩发烧后又吐怎么办 11个月宝宝吐了怎么办 11个月宝宝拉肚子怎么办 2岁宝宝反复呕吐怎么办 1岁半幼儿拉肚子怎么办