每天进步:2014年10月几篇
2014-10-15
批处理设置ip,条件跳转。
gdb调试,断点b,单步进入子函数s,单步n,watch观察变量。
samba用户管理,smbpasswd -a username
。
虚拟用户。
文件夹权限设置smb.conf。
samba权限后还有系统权限。
cx寄存器循环中做临时变量。
2014-10-16
计算机中数据有多重含义,比如字符@
或数值64
或者让AX寄存器自加1
的机器指令,在内存中是完全一样的,都是01000000。
标志寄存器,CF
进位标志位,OF
溢出标志位,PF
奇偶标志位,SF
符号标志位,ZF
零标志位。
有符号数运算,溢出仅发生在同号相加得异号时。
include
汇编子程序
adc
,sbb
带进借位加减法指令
在内存中原来数组中直接做修改时候,要注意转换后数据长度是否能够存放下。
子程序单独运行正常,与其他程序混用异常,可能是寄存器冲突,需要出入栈保护操作。
2014-10-17
内终端处理机制。
单步中断标志位TF
。
中断向量表,保存中断例程入口地址。
0除法溢出中断,中断例程入口保存在00000,00002。
1单步中断,例程入口00004,00006。
cpu上电首先运行FFFF0处的跳转指令,
然后执行BIOS硬件检测程序和初始化程序,
初始化程序会建立BIOS中断例程的向量表,
然后调用25号中断进行操作系统引导。
操作系统会建立自己的系统中断例程向量表,
而且系统中断例程需要加载入内存常驻。
2014-10-18
端口读写指令:in
、out
。
端口即相关功能芯片的寄存器,其为间接访问功能芯片内存提供了途径。
cmos中系统时间信息以BCD码形式存储在前几个内存单元中,
可以通过70H、71H号端口间接访问,
70H为地址只写端口,
71H为数据读写端口。
BCD码用四位二进制数表示一位十进制数。
有条件跳转指令,无符号数跳转,je
、jne
、jb
、jnb
、ja
、jna
,
原理为通过检测标志寄存器相关标志位(ZF
、CF
),进行是否跳转操作,
常与cmp
指令连用分别表示相等则跳转、不等则跳转、小于则跳转、不小于则跳转、大于则跳转,不大于则跳转。
2014-10-19
端口和中断机制,是cpu进行I/O的基础。
键盘芯片通过扫描得知键盘开关状态,键盘按下产生通码,松开产生断码,芯片会向cpu发出9号中断,该中断是可屏蔽的外中断。
断码=通码+80h
数值的计算中无法通过结束符标识数值长度,因为任何符号的本质都是数字。
所以要想明确数据长度必须明确规定存储数据长度的寄存器或内存单元。
cpu可以通过执行循环语句来达到延时的目的。
2014-10-21
类是C++在C下引入的新数据类型,为面向对象编程提供依据,封装继承多态是其特点。
C++比其他高级语言多了多继承机制。
比C增加流的概念。
重载了左移位、右移位运算符来实现流的插入和提取。
增加命名空间。
保留了C原有的所有特征。
规定主函数必须返回整形。
setprecision(n)
控制精度,与setiosflags(ios::fixed)
合用小数点精度,与setiosflags(ios::scientific)
合用指数输出,默认setprecision(6)
,头文件iomanip。
endl
换行,\n
换行,10(16进制A)
换行。
getchar()
,putchar()
,接收整型返回整型ASCII。
2014-10-22
string是C++中一个类。
重载运算符实现了string数据的比较(== < >)。
setw(int)
填充空位,setfill(char)
用字符填充。
gdb调试程序:
p 变量
查看变量值,
b 行号或函数名
设置断点,
display /i $pc
汇编级调试,
si
单步运行,
d
删除断点,
i r
显示寄存器值,
i r eax
显示eax寄存器值。
do{} while();
先执行再判断,
while()
先判断再执行。
udp端口无法telnet测试。
查看端口和占用进程号:netstat -ano | findstr 端口号
查看特定进程号的进程应用:tasklist | findstr 进程号
2014-10-26
cout<<X
,是一个表达式,其中cout
是左操作数,<<
是操作符,X
是右操作数。
cout
为一个对象,属于ostream
类。
C++标准库中还定义了其他三个IO对象,分别是标准输入cin
,标准错误cerr
,clog
。
iostream
库有两个类,istream
类和ostream
类,是输入流和输入流,流即字符序列。
输入输出类对象要绑定相应输入输出设备,例如cin
对象绑定键盘设备。
操作符<<
和>>
在C++中被重载为输出操作符和输入操作符,操作符返回值为左操作数。
所以cout<<a<<b
相当于(cout<<a)<<b
cout<<a
先运算,运算结果返回左操作数cout
,所以下一步运算(cout)<<b
。若cout<<(a<<b)
则编译报错。
可以利用运算符重载定义对象之间的运算,如通过重载运算符+
定义对象1+对象2
的处理和返回结果等。
程序语言定义基本类型和形成更复杂类型的机制,
利用这些机制定义的更复杂类型形成标准库,
在标准库基础上能够更容易的开发出复杂的应用程序。
按照从基本到一层层封装,从灵活多变的可能性到特定功能,次序为:
词汇表(基本数据类型,基本操作符,程序控制语句)-> 标准库 -> 应用程序。
开发一门新语言的次序也是如此,原则上到词汇表层面新语言便诞生了,
加入标准库是对含有某些功能子程序的封装,方便开发。
2014-10-27
汇编不得不考虑的代码地址边界问题。
汇编程序中,由CS
和IP
两个寄存器指向下一刻要运行的代码。这面临一个问题,就是指令地址的正确计算。
首先,每读入一条指令,IP
的值会自动加指令长度,一旦IP
有进位,则指令的进行往往会不按照源程序的意图,因为一般情况下指令是在内存中连续存放的,而IP
产生进位值会回到0重新开始,这样相当于回到前面的某个内存单元继续执行指令。
所以操作系统在分配内存时,要考虑这种情况,编译器也要检查程序代码的长度是否超过IP
寄存器的寻址空间,在8086下是64kb。
程序员要在编写超过64kb的程序时使用跳转指令,分段存放代码。
用jmp far ptr
或call far ptr
指令。
这又存在另外一个问题,就是编写的程序中当前IP
值的获取。
一般情况下,使用offset
标号的形式来获取代码的偏移地址,但是一旦无法供编译器提前获取标号处地址的情况出现,将引起程序进程的混乱,这时候可以使用下面的指令获取当前IP
值:
call 标号
标号: pop ax
这样ax中便保存有程序运行时候的IP
地址了,而不管当前程序运行在哪一段内存空间中。
然后用当前IP
加上偏移量就可以获得程序任意一处的IP
地址了。
2014-10-30
有关汇编中跳转指令的注意事项:
汇编编程中,由于有些功能程序需要被安装后使用,而安装的内存地址有时候是不确定的。
因此在功能程序中,尽可能不使用标号的偏移地址来确定数据位置。
这是个在编程时需处处小心的问题,一旦出问题调试起来是很麻烦。
这要求我们在使用跳转指令时一定要小心和考虑周到,减少将来调试和维护的麻烦。
call
,jmp
,je
等跳转指令,指令中有时候是相对位移,有时候是绝对地址,无论哪一种情况,都有可能在程序的地址变化后出现错误,都需要小心对待。
相对位移的跳转指令,需要在程序移动前后,跳转指令和跳转目的标号间的相对位置不变。
在编写子程序时候,如果不能确定将来子程序的调用者在何种环境下调用子程序,就不能使用绝对偏移地址。绝对偏移地址一般是编译器在程序编译时被计算出的。比如offset
伪指令。
尤其是在安装中断的时候,由于中断程序被安装到固定的内存区域,所以中断程序中的偏移地址,我们需要用中断安装后的内存绝对地址来重新计算。
总结起来,跳转指令分为两类:
一类是根据相对位移完成的跳转,一般叫近转移和短转移。跳转指令中给出标号,这类跳转指令要保证程序在执行的时候,跳转指令和目的标号的相对位置不变。
另一类是绝对位置的跳转,跳转指令中给出 far
标号或者给出寄存器或者给出一个字或双字的内存单元地址(其中还包括ret
,iret
指令)。这样的跳转指令是绝对位置的跳转,要注意跳转目的程序段的绝对地址。
如果只是改变IP
的跳转,还要考虑跳转指令和目的程序段的段地址是否相同。
汇编程序调试的方法:
由于汇编运行在较底层的硬件环境下,有时候甚至需要脱离其他软件环境运行程序(裸机或类裸机),所以很多时候我们无法单步调试我们的汇编程序,这是很麻烦的,要求我们一步步一点点的想办法间接调试程序。
我们可以改变代码来调试,把运行在特殊环境下的程序移植到一般环境下再调试,前提是不改变程序大的逻辑结构。
比如安装9号键盘输入处理中断例程,程序一旦出现问题很容易造成键盘失灵,而无法进一步调试。
我们可以先把中断号改为7,间接调试逻辑相似的程序,排除一些明显的错误再慢慢修正回原来的程序。
还有一个调试程序的通用方法就是一点点的去除代码,等bug消失后再慢慢增加代码,进而确定bug出现的代码片段,减小盲目性。