每天进步:2014年11月几篇

2014-11-02

C语言中的函数对应汇编中的子程序。
c语言中,子程序返回值一般用寄存器AX传递,临时变量大都保存在栈段中。
调用函数前,会先把要传递给函数的参数入栈,然后CPU把当前的IP寄存器入栈,以便函数调用完后返回时用。
然后CALL进入函数。进入后先把BP寄存器入栈,再MOV BP,SP。函数执行过程中BP的值从这一刻开始一般不变。
如果函数中有变量,会继续往栈顶写入。
用BP作为函数栈中的基准指针来读取函数的参数或变量。
例如BP+4就是函数传进来的第一个参数,BP+6是第二个……以此类推。
BP - n(n是正整数)一般是函数内的临时变量。

常量一般保存在数据段(段地址为DS),偏移地址一般是一个常数不是内存中的值。

函数中的指针和变量没有本质的区别,在汇编看来都是相同的数据,一般都保存在内存中。但是意义上不同:
普通变量一般是做计算用,直接取了可以用;
指针变量除了本身保存在内存中做普通变量用外,还有间接寻址的作用,一般会把它的值先移到BX或DI、SI寄存器中,然后寻址找出相关内存中的数据例如[BX]

用指针寻址多做一步所以比较慢。

以上原理仅适用于CPU实模式下。

贴一个用C语言写的printf函数,仅实现了显示%d%c功能,可以接收不定量参数。

void nprintf(char *p, ...)
{
  int num,j;
  char c[20];
  int count = 0;
  int i_out = 0;
  int i;
  for(i=0; p[i]!='\0'; i++){
    if(p[i]== '%'){
      if(p[i+1] == 'd'){
        count++;
        num = *(int far *)(_SS*0x10000+_BP+4+2*count);
        for(j=0; num!=0; num/=10){
          c[j++] = num % 10 + 0x30;
        }
        while(j != 0){
          *(char far *)(0xb8000000+160*12+2*i_out++) = c[--j];
        }
        i++;
        continue;
      }
      if(p[i+1] == 'c'){
        count++;
        *(char far *)(0xb8000000+160*12+2*i_out++) = *(char far *)(_SS*0x10000+_BP+4+2*count);
        i++;
        continue;
      }
    }
    *(char far *)(0xb8000000+160*12+2*i_out++) = p[i];
  }
}
main(){
  nprintf("char: %c, num: %d, hehe%c.", 'H', 31415, '3');
} 

2014-11-05

windows窗口编程原理:

GetMessage检查系统消息队列中的MSG结构,
MSG第一个字段为消息发向的窗口句柄,用其同自己第2个参数做比较,若MSG是发送给自己接收的,则将队列中的MSG相关字段写到自己第一个MSG指针指向的内存区域。

DispatchMessage函数以GetMessage写好的MSG结构前四个字段作为参数,调用窗口类的回调函数(窗口过程),回调函数会根据传进来的参数进行相应的处理。

比如,鼠标左键点击窗口的关闭按钮松开时候,windows系统会把这个点击事件封装成一个MSG结构,其中记录了点击这一事件的全部信息。
包括被点击窗口的——

  • 窗口句柄
  • 事件类型:WM_LBUTTONUP(等效于十六进制的202)
  • 详细参数
  • 消息放入队列的时间
  • 鼠标坐标

窗口所属的线程调用GetMessage函数,会获得这个MSG结构并复制存储,线程调用DispatchMessage函数,该函数会调用窗口所属的窗口类的窗口过程(也叫回调函数,实际就是一个子程序)来处理这个点击事件。
窗口过程中对WM_LBUTTONUP事件类型做出处理,比如关闭窗口释放资源等操作。

整个过程中,事件在内存中是以MSG结构的形式存储的,相关函数也是根据MSG结构对事件进行判断和处理的。

对窗口事件的捕获并进行封装成MSG结构是windows操作系统来完成的,对窗口过程的回调也是windows操作系统完成的。这些我们在编程时不必考虑细节。
但是为了让windows系统能够正确的找到相应的窗口类的窗口过程,在建立窗口类的时候我们需要指定所建立的窗口类的回调函数地址。
我们调用系统提供的RegisterClassEx函数来建立窗口类,这个函数需要知道我们建立的窗口类的相关属性信息,我们要把相关信息作为参数传给它。
具体的:
这个函数接收一个包含将要建立窗口类属性信息的WNDCLASSEX结构作为参数。 WNDCLASSEX结构中有一个字段是lpfnwndproc,这个字段的内容即所建立的窗口类的回调函数地址。
由同一个窗口类创建出来的所有窗口对象都使用一个窗口回调函数。
还有一个SendMessage函数能够直接给窗口对象发送消息,这个函数的第一个参数是所发送的消息的目的窗口对象的句柄,第二个参数是窗口事件类型。
PostMessage函数能够往相关窗口对象消息队列中发送消息事件。

2014-11-06

windows下环境变量的设置

%变量名字%会替换成相应变量代表的字符串。
如在命令行下echo %path% 可以输入path变量的字符串。

源程序中include文件的默认查找路径在include变量中, 可以用set include=“路径”设置,用echo %include%查看。

lib变量是源程序中includelib的默认查找路径。

posted @ 2019-01-02 16:07  xuejianbest  阅读(121)  评论(0编辑  收藏  举报