汇编基础(2)

分段写法:
assume的时候要声明一下,ds:xx或者cs:xx。声明哪个段寄存器会用到哪个segment
xx segment
数据或者code
xx ends
要引用的时候。就是引用xx这个名字,作为段地址。但是这个不能直接赋给段寄存器,要拿个通用寄存器中转一下。

话说,如果我写成了,一个segment里面包含多个segment的形势。。也可以编译呀。。神奇

汇编里面是用分号做注释符。。。

assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0234h  ;0452h,0eabh,0987h,0452h,0eabh,0765h
data ends
stack segment
dw 0,0
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,data
mov ds,ax
push ds:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax,4c00H
int 21H
code ends
end start
——————内存分配——————

这一段代码,居然给ds开辟了16个子节点内存空间。是不是16位的cpu分配内存的最小单位就是16字节呢。。也就是10H。。

不过也应该是这样,要不然段地址写不了呀,至少要+-1哦。

所以说,我们一般写segment的时候,CPU给的应该都是10H倍数的内存吧。。

——————segment顺序——————

把data和stack写在code segment后面,内存分配很不同,当然是data和stack的内存位置关系

cpu按照code 的长度,分配了30H的内存给它。

mov ax,4c00H的机器码是 B8 00 4C

int 21H的机器码是CD 21

然后是data的10H和stack的10H。

明明白白的说明。。CPU只是一条筋只会顺序分配内存。

多个segment来写,自然是在导入编译后的代码的时候,就分配内存了。当然了,ds,ss的值要等到执行才会有赋新值。

并且,data和stack的内存区域,在调用的时候,才会有一个初始化操作

——————栈————————

cpu给一个栈的初始状态并不是所有值都为0的,CPU会自动生成一些字节,不知道为何,只能理解为通信使用。带有几个字节的尾巴,说明这是一个栈的空间。

push是没有问题的,pop之后,原来的位置就被某些不明白的字节替代了,也许是cpu用来通信用的。

——————or和and————————

原来大写和小写的区别就是小写比大写多20H,

“and 8位寄存器,置换码” 就可以解决小写变大写问题

置换码:11011111b的与运算就可以将第6位置为0 ,这样该段能显示出字母的ASC2码就必须呈现为大写形式了。

用“or 8位寄存器 置换码”解决大写变小写问题

置换码00100000b的or运算,就可以把第6位置1,这样必须字母就必须成为小写了。

————————[bx+i]————————————

这个比较有趣,mov ax,[bx+i]是可行的,相当于:

mov ax,[bx]

add bx,i

而且还有几种通用写法:

[i+bx]

i[bx]

[bx].i

话说php是不是学最后一种的来的?汇编里面已经有”.”的定义了吧。。

i[bx]的方式,其实是数组的原型吧。

用[bx+i]的方式,就可以在同一个循环中,同时处理2个地址。

汇编的灵活性非常大哦。。

下面是一个2重循环的例子,目的是把datasg中的,前4个字母变大写:

assume cs:codesg,ss:stacksg,ds:datasg

stacksg segment

dw 0,0,0,0,0,0,0,0

stacksg ends

datasg segment

db ’1.  display     ‘

db ’2.  brows       ‘

db ’3.  replace     ‘

db ’4.  modify      ’

datasg ends

codesg segment

start:

mov ax,datasg

mov ds,ax

mov ax,stacksg

mov ss,ax

mov sp,0010H

mov cx,4

mov si,4

myloop:

push cx

mov bx,0

mov cx,4

myloop0:

mov al,ds:[bx+si]

and al,11011111b

mov ds:[bx+si],al

add bx,16

loop myloop0

pop cx

inc si

loop myloop

mov ax,4c00H

int 21H

codesg ends

end start

————————程序说明————————
1.两个循环,不能用tab缩进第二个,汇编的语法对于tab支持的不太好,这样就写不出美观的程序了
2.cx放在一个栈中进行数值保护,这样,内层循环不会影响外层循环的迭代子。
3. bx记得要归0。。
4.debug的时候,不能省事的一次g 到很后面。因为程序很行,所以第一次先执行第一页,g 1e,然后再用个g ff。。或者什么的,g到比最后还后就OK了。

汇编基础(1)

第一个程序:

masm貌似是用得最多的编译器了哦。。初次使用masm5。

汇编领域的hello world:

用cmd中的edit窗口写了一个bb.asm:

assume cs:bb
bb segment
mov ax,2
add ax,ax
add ax,ax
mov ax,4c00H
int 21H
bb ends
end
汇编的语法很不美观哦。。非常低级的语言,不过也能让人看得很清楚,这个CPU是怎么操作数据的。
最后这两行是用来返回的,给我的感觉是返回command.com这个命令解释器的。
mov ax,4c00H
int 21H
话说 asm是assemble的简写哦。。
其中CX是程序的长度。CS指向程序的开始执行的内存地址。DS是程序存放的段地址。DOS中有个256位的PSP通信区,所以CS和DS之间间隔了10H。
记住在debug中用p命令来执行int 21。
用 g 后面跟16进制数值,表示一次执行到哪一步。可以用它跳过循环,用p也可以
汇编里的循环是使用cx作为迭代子
语法:
mov cx,(value)
s:(code)
loop s
虽然debug里面可以给寄存器赋值ffff。。但是汇编里面要写0ffffH。前面加0,后面加H
一个简短的算术代码,是要取ffff6里面的值乘3次,放到dx里面。
assume cs:bb3
bb3 segment
mov ax,0ffffH
mov ds,ax
mov bx,6
mov ah,0
mov al,[bx]
mov dx,0
mov cx,3
s:add dl,al
loop s
mov ax,4c00H
int 21H
bb3 ends
end
因为地址里面的值是字节,要赋值给寄存器的低位才行。
masm中[0]会识别为0,可以采用上述代码的替换,也可以使用ds:[0]的方式
——————————
用新建数据的方式来开辟内存空间,并且在处理数据的时候,dw一组更大的空间。这样可以开辟出连续的空间来,作为栈
栈的sp看似很简单,但是配合其cpu的低位高位的机制,就让人有点乱了。
比如说,我们知道48个字节可以放24个字单元,48个字节是30H,那么,我们要建一个可以放24个字单元的栈,SP就要设定为0030H。
我们要放5个字单元呢,那就是要把SP设为000AH了。
而且,栈是一种这样的东西,你最先进去(push)的数据,站的地址是最大的。它的高位是占到SP-1的位置。低位自然是SP-2
loop所用的是CX的减法,控制了循环的数量。这样的情况下,我们不必担心循环没有终止。
有时候循环中间还需要累加,这时候只能用其他的寄存器做add了。
————————
代码要让人更清楚思路,当然需要分段。
虽然CPU是不会理会这些伪代码的分段。(汇编这个叫伪代码,那么高级语言的话或者脚本语言。。是不是基本没有不伪的代码了?基本都是封装过的)

认识CPU(2)



jmp命令用来简单的转移,可以写jmp 2000:1000,或者单独写jmp 1000,后者表示单独调整ip

这样的话,要用a命令写汇编的时候,要写 a 2000:1000 要指明,不然用t没法执行。。

debug命令挺好玩的。

r是用来显示寄存器。

d是用来列出内存中的内容,用“d  段地址:偏移地址”可以查8*16个内存单元。再使用d就可以查后续。

也可以指定最大偏移,使用“d  段地址:最小偏移地址 最大偏移地址”这样可以查一个指定范围,当然最大最小如果相同,就是指定查找1个。

e命令式用来改写内存中的内容的,可以用“e 起始地址 数据 数据 数据…”来改写起始地址以及之后的地址的值。

也可以用另一种提示的方法修改:比如输入e 0b2d:30a 这是光标会停在”.”后面,前面是该内存单元的值,可以输入想要的值。继续修改下一个就按space,修改完成就按enter。

t是用来执行用的,记得执行之前要用 r cs 和r ip 来指定要执行的内存地址

a 是用来写汇编语句的,当然要写之前,先要执行“a 段地址:偏移地址”这样才能写特定的地址段

在ffff:0 f这个地址段是存有主板bios的日期,当然,这个是rom,改写不了的。

4个通用寄存器,AX BX CX 和DX

段寄存器:CS DS SS ES

CS 代码段寄存器 (记录代码执行的段地址)

DS 用来存放要访问数据的段地址

IP 指令指针寄存器(记录偏移地址)

我们往通用寄存器里写数据是很容易的,比如就是写mov ax,1000H

但是要读写一个内存单元的数据呢,我们要如何写呢?

这时候就要用到一个DS,作为中介,存下需要访问的段地址

具体使用方法:

段寄存器不能用数据来直接赋值,mov ds,1000H是不能够的,这是Intel的CPU禁止的。

但是我们可以用通用寄存器给段寄存器赋值。。这又是用通用寄存器来做中介。。2次中介。。

比如说,我们要读写10000H(这是实际地址,段地址是该地址/16)这个地址上的数据

我们这样写:

mov ax,1000H

mov ds,ax

mov ax,[0]

其实[0]是[0000]的简写,是偏移地址值,使用[],cpu会自动调用ds

这样ax里,al保存的是地址10000H的值,ah保存的是地址10001H里的值。

如果我们要写地址,那么我们要给地址单位赋值:

地址单位也必须是通过寄存器来中转复制的,可以使通用的,也可以是段的

mov [0],ax

这样10000H保存的是al,10001H保存的是ah。

这是因为8086CPU的位数关系,一次是16位,在内存中表现为一个字单位,2个字节。。

可以给[]赋值,它接受寄存器,段寄存器为值,这样改写的是内存单元

给ds赋值,它接受寄存器,内存单元为值,这个就比较奇妙了:

把[0]赋值给ds,这还好,如果把[1]赋值给ds,这样ds就改了,[0],[1]就更新了,呵呵

那如果我这么做,可操作的内存地址是不是可以存在某个地方,然后统一调用?

栈,是由ss段寄存器和sp偏移寄存器里指向栈顶元素的。存入和取出栈内的字,sp都会-2或者+2

以10000H为例,我们要做一个10000H~1FFFFH的栈,那么,SS要设为1000H,sp要设为0.

为什么是0呢,因为如果栈里有一个字的话,sp指向的是这个元素低位,一个字占据1FFFF和1FFFE的位置,sp指向FFFE。

那么当栈为空的话,sp+2,就为0了。

那如果栈是满的情况呢?当然,还是0了。如果还要继续压栈,就循环覆盖了。

我们设栈的时候设定为16的倍数,以F结尾,最大是0~FFFF也就是64K。

当然,压入栈中的,是寄存器,也可以是内存单元。

其实就是对内存的一种人为分段,就像写代码时候一段一段的。不过这种分段的制度很重要。话说编程最喜欢的也就是分段了。。要切成一小块一小块的。

debug的D命令后面跟的地址,应该是放到ds寄存器中的。

debug的T命令在执行修改SS的操作时,下一条指令会跟着执行

认识CPU(1)

储存程序型计算机 ,程序写在内存中。

内存:DRAM,随机存取存储器。

随机存取:指的是当存储器中的消息被读取或写入时,所需要的时间与这段信息所在的位置无关。

内存中用电容的充电来表示数据,充满为1,空为0。

静态随机存取存储器Static Random Access Memory, SRAM)是随机存取存储器的一种。所谓的“静态”,是指这种存储器只要保持通电,里面储存的数据就可以恒常保持。相对之下,动态随机存取内存(DRAM)里面所储存的数据就需要周期性地更新。

2、SRAM 对称的电路结构设计,使得每个记忆单元内所储存的数值都能以比 DRAM 快的速率被读取。

3、SRAM 通常都被设计成一次就读取所有的资料位元 (Bit),比起高低位址的资料交互读取的 DRAM,在读取效率上也快上很多。

提到SRAM,就不得不说到cache。

Cache一词来源于1967年的一篇电子工程期刊论文。其作者将法语词”cache”赋予“safekeeping storage”的涵义,用于电脑工程领域。

CPU访问内存的时间一般为数个clock。

高速缓存中的数据:1)暂存刚刚访问过的数据,2)从内存中取到将要使用的数据预先。

复杂指令集CISC,Complex Instruction Set Computer)是一种微处理器指令集架构(ISA),每个指令可执行若干低阶操作,诸如从内存读取、储存、和计算操作,全部集于单一指令之中。

SIMD:在微处理器中,单指令流多数据流技术则是一个控制器控制多个平行的处理微元,例如IntelMMXSSE以及AMD3D Now!技术。

寄存器register),是中央处理器内的其中组成部份。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据地址

常用的指令集架构是CISC,还有一种EPIC指令集架构,用在64位安腾windows XP和2003上。是Intel的IA-64架构,这个是英特尔的优势所在吧?

x86是一种CISC

宏,计算机科学里的宏是一种抽象,它根据一系列预定义的规则替换一定的文本模式。宏的用途在于自动化频繁使用的串行或者是获得一种更强大的抽象能力

MASM 一种汇编器,是ms-dos上的汇编器。http://www.movsd.com/ 这个网站上有一些MASM的资料

不过还是不太懂。。。我的理解是就是在机器语言(操控cpu,内存)的基础上,做了一些宏,写了一些符号帮助简化操作。没有试过。。
x86,感觉很深,以后再看这个的wiki。

差不多所有的冯·诺伊曼CPU的运作原理可分为四个階段:提取解碼执行写回

第一階段,提取,从程序記憶體中檢索指令(为数值或一系列数值)。由程序計数器指定程序記憶體的位置,程序計数器保存供識別目前程序位置的数值。换言之,程序計数器記錄了CPU在目前程序裡的蹤跡。提取指令之后,PC根據指令式長度增加記憶體單元[iwordlength]。指令的提取常常必须从相对较慢的記憶體尋找,导致CPU等候指令的送入。这个问题主要被论及在現代处理器的快取和管線化架构(见下)。

CPU根據从記憶體提取到的指令来決定其执行行为。在解碼階段,指令被拆解为有意義的片斷。根據CPU的指令集架构ISA)定義将数值解譯为指令[isa]。一部分的指令数值为运算碼,其指示要进行哪些运算。其它的数值通常供給指令必要的資訊,諸如一个加法运算的运算目标。这样的运算目标也许提供一个常数值(即立即值),或是一个空間的定址值:暫存器記憶體位址,以定址模式決定。在舊的设计中,CPU裡的指令解碼部分是無法改变的硬体装置。不过在眾多抽象且复杂的CPU和ISA中,一个微程序时常用来幫助转换指令为各種形態的訊号。这些微程序在已成品的CPU中往往可以重写,方便变更解碼指令。

在提取和解碼階段之后,接著进入执行階段。該階段中,連接到各種能夠进行所需运算的CPU部件。例如,要求一个加法运算,算术逻辑单元将会連接到一组輸入和一组輸出。輸入提供了要相加的数值,而且在輸出将含有總和结果。ALU内含電路系統,以于輸出端完成简单的普通运算和逻辑运算(比如加法和位元运算)。如果加法运算產生一个对該CPU处理而言过大的结果,在标誌暫存器裡,溢出标誌可能会被設置(參见以下的数值精度探討)。

最终階段,写回,以一定格式将执行階段的结果简单的写回。运算结果極常被写进CPU内部的暫存器,以供隨后指令快速存取。在其它案例中,运算结果可能写进速度较慢,但容量较大且较便宜的主記憶體。某些类型的指令会操作程序計数器,而不直接產生结果資料。这些一般稱作「跳轉」並在程序中帶来循環行为、條件性执行(透过條件跳轉)和函式[jumps]。许多指令也会改变标誌暫存器的状态位元。这些标誌可用来影響程序行为,緣由于它们时常显出各種运算结果。例如,以一个「比较」指令判斷兩个值的大小,根據比较结果在标誌暫存器上設置一个数值。这个标誌可藉由隨后的跳轉指令来決定程序动向。

在执行指令並写回结果資料之后,程序計数器的值会遞增,反覆整个过程,下一个指令周期正常的提取下一个順序指令。如果完成的是跳轉指令,程序計数器将会修改成跳轉到的指令位址,且程序繼續正常执行。许多复杂的CPU可以一次提取多个指令、解碼,並且同时执行。这个部分一般涉及「經典RISC管線」,那些实際上是在眾多使用简单CPU的電子装置中快速普及(常称为微控制器[riscpipeline]

第一步:提取:指令开始,CPU要去内存找指令,命令寄存器到内存中去定位,并保存一个该指令在内存的起始地址,返回这个指令式子的长度。CPU收到式子后,就根据这个长度分配更多的内存来存这整个式子。

第二步:解码,CPU处理式子,根据结果不同可能返回的是一个地址(寄存器的或者是内存的)或者是一个值。(写微程序可以改变CPU解码方式)

第三步:执行,就是调用CPU的逻辑单元

第四步,写回,CPU根据式子的不同,有些式子包含逻辑关系,会在标志寄存器中留下值,简单的数值会留在寄存器中,而大量的数据会放在内存中。

如果是跳转指令,寄存器中会留下跳转到指令地址所在的内存地址。

所以咱写程序都是一股脑往内存里面写呀。。然后让CPU分配内存。

php学习摘引01

在php的注释中,有一个?>结尾符的问题,就是单行注释的时候,遇到这个结尾符,php就跳出了,注释会被override掉

这里有个评论,讲了这个这样的代码写法:

a trick I have used in all languages to temporarily block out large sections (usually for test/debug/new-feature purposes), is to set (or define) a var at the top, and use that to conditionally comment the blocks; an added benefit over if(0) (samuli’s comment from nov’05) is that u can have several versions or tests running at once, and u dont require cleanup later if u want to keep the blocks in:  just reset the var.

personally, I use this more to conditionally include code for new feature testing, than to block it out,,,, but hey, to each their own :)

this is also the only safe way I know of to easily nest comments in any language, and great for multi-file use, if the conditional variables are placed in an include :)

for example, placed at top of file:

<?php $ver3 = TRUE;
$debug2 = FALSE;
?>

and then deeper inside the file:

<?php if ($ver3) {
print(“This code is included since we are testing version 3″);
}
?>

所以我们不要注释掉程序语句,而是采用这样的判断来做

http://docs.php.net/manual/zh/language.variables.php 这里有个字符类型转换库的代码

http://docs.php.net/manual/zh/userlandnaming.php mb_convert_encoding(‘&#’.intval($u).’;', ’UTF-8′, ’HTML-ENTITIES’);看不懂的

引用赋值,这个要记录下:

<?php
$foo = ’Bob’;              // 将 ’Bob’ 赋给 $foo
$bar = &$foo;              // 通过 $bar 引用 $foo
$bar = ”My name is $bar”;  // 修改 $bar 变量
echo $bar;
echo $foo;                 // $foo 的值也被修改
?>

PHP 中最具争议的变化就是从 PHP » 4.2.0 版开始配置文件中 register_globals 的默认值从 on 改为 off 了

<?php
if (isset($_COOKIE['MAGIC_COOKIE'])) {

// MAGIC_COOKIE 来自 cookie
// 这样做是确保是来自 cookie 的数据

} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {

mail(“admin@example.com”, ”Possible breakin attempt”, $_SERVER['REMOTE_ADDR']);
echo ”Security violation, admin has been alerted.”;
exit;

} else {

// 这一次请求中并没有设置 MAGIC_COOKIE 变量

}
?>

当然,单纯地关闭 register_globals 并不代表所有的代码都安全了。对于每一段提交上来的数据,都要对其进行具体的检查。永远要验证用户数据和对变量进行初始化!把error_reporting() 设为 E_NOTICE 级别可以检查未初始化的变量。

http://docs.php.net/manual/zh/language.constants.predefined.php 预定义常量

http://docs.php.net/manual/zh/reserved.variables.php 预定义变量

http://docs.php.net/manual/zh/reserved.variables.server.php server变量,这个又很多需要使用到的哦,server里面的

<?php
// first use encodeURIComponent on javascript to encode the string
// receive json string and prepare it to json_decode
$jsonStr = stripslashes ($_POST['action']);
// decode to php object
$json = json_decode ($jsonStr);

// $json is now a php object
?>

file上传

http://docs.php.net/manual/zh/function.move-uploaded-file.php 这里讨论了file上传时的一些问题和功能完善

http://docs.php.net/manual/zh/features.file-upload.errors.php 各种上传error值

<input type=”file” multiple=”true” name=”files[]“/> 这个在html5中可以支持

数组:

http://docs.php.net/manual/zh/ref.array.php 数组方法

类:

http://docs.php.net/manual/zh/ref.classobj.php 这里有一些类所具有的函数

http://docs.php.net/manual/zh/language.oop5.decon.php 类的构造函数和多构造函数

http://docs.php.net/manual/zh/language.oop5.abstract.php 这里有一段介绍接口和抽象类的

function的内部函数:

未定义的属性赋值时引发:

void __set ( string $namemixed $value )

mixed __get ( string $name )

使用isset和unset时引发

bool __isset ( string $name )

void __unset ( string $name )

未定义的方法调用时引发:

mixed __call ( string $name , array $arguments )

mixed __callStatic ( string $name , array $arguments )

可以通过foreach来迭代对象中的 public属性

http://www.php.net/~helly/php/ext/spl/ 标准php库。。这里面好多东西。。

要重做数组的迭代器:

首先是iterator接口的实现:

里面有5个方法要实现,他们的首次顺序是:

1 rewind():Rewind the Iterator to the first element.

2 valid():Check if there is a current element after calls to rewind() or next().

3 current():Return the current element.

4 key():Return the key of the current element.

5 next():Move forward to next element.

6 current()

7 valid()

之后的顺序就是从 3 current开始 执行5步,碰到最后一个元素时,next以及next之后都为空

里面有个iteratoraggregate ,看了一下

iteratorAggregate::getIterator()

Returns:
an Iterator for the implementing object.

Implemented in ArrayObject.

要使用这个数组iterator 可以实例化这个实现了iterator的类,也可以在写另外一个类(类B),这个类实现iteratorAggregate接口

并在类B中实现接口中的getIterator()方法,这个方法要求返回一个iterator

这样,我们就重写了类中的变量存放数组的遍历方式。在使用foreach的时候,就不一样了。

http://docs.php.net/manual/zh/ref.spl.php 这里有SPL方法,比如class_implements($class_name或者new class) 和class_parents($class_name或者new class)

http://docs.php.net/manual/zh/language.oop5.patterns.php 这里讲模式,讨论了很多单例模式。。不太懂

魔术方法:

__construct__destruct (参看 构造方法和析构方法), __call__callStatic__get__set__isset__unset (参看 重载), __sleep__wakeup__toString,__set_state 和 __clone

http://docs.php.net/manual/zh/language.oop5.magic.php

http://docs.php.net/manual/zh/language.oop5.typehinting.php#86216 typehint,有段代码Daniel写的,不过看不懂。。

他的代码意图:

People often ask about scalar/basic typehints.  Here is a drop in class that I use in my MVC framework that will enable typehints through the use of a custom error handler.

1) Because people are sick of using the is_* functions to validate parameters.
2) Reduction of redundant coding for defensive coders.
3) Functions/Methods are self defining/documenting as to required input.

意图就是:摒弃is_*function ,用typehint来确定参数的基础类

静态调用:

http://docs.php.net/manual/zh/language.oop5.late-static-bindings.php

有3个例子,第一个例子告诉我了,这个有些类似$this来调用,不过是用来调用static方法的。

第二个例子不好,我把static换成self,结果是一样的。

第三个例子告诉我,用self和parent,结果是一样的

最后结果就是,static的静态方法,有越级的功能,子类的static方法可以覆盖父类同名static方法

第 29 页,共 32 页« 最新...10202728293031...最旧 »