assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data ends
stack segment
dw 0,0,0,0,0,0,0,0
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,16
mov ax,code
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
CPU执行程序,程序返回前,cs,ss,ds与code,stack,data所指代的地址为什么code是一致,而后两者不同,而且差值也不同?
6 个解决方案
#1
经过我的研究,发现上面的研究过程有点小问题。
首先,ss在后面有个赋值,我没有执行到那一步去看。
再者忘记了在程序内存中,还有PSP这么个特别的东西。
整理了一下,在我的模拟环境中,上面程序,执行到最后,有如下内存结构分布。
所以说,可见,ss最后和stack是一致的,ds+10h(psp长度)= data,cs = code
但是我又想到,这里的cs与code的相等并未明确赋值,而ss,ds都有对应的mov语句将他们改动到了stack,data上,
所以我想知道,stack实际指向的是什么?data指向什么?code应该是和cs一样的吧。
首先,ss在后面有个赋值,我没有执行到那一步去看。
再者忘记了在程序内存中,还有PSP这么个特别的东西。
整理了一下,在我的模拟环境中,上面程序,执行到最后,有如下内存结构分布。
所以说,可见,ss最后和stack是一致的,ds+10h(psp长度)= data,cs = code
但是我又想到,这里的cs与code的相等并未明确赋值,而ss,ds都有对应的mov语句将他们改动到了stack,data上,
所以我想知道,stack实际指向的是什么?data指向什么?code应该是和cs一样的吧。
#2
对 .exe 类的来说,程序刚载入时,CS:IP 指向你程序的入口;SS:SP,如果你的堆栈段定义用了 STACK 修饰(mystack segment
stack),则也会指向到你的栈;DS 和 ES 则是指向 PSP,后面指向哪里需要你自己的代码来做。
#3
计算机的内存管理单元是以“字节”为最小单位进行线性编址的,字节是80x86CPU对内存管理的基元。为了标识每个存储单元,就给每个存储单元规定一个编号,该编号就是内存单元的物理地址。
存储单元的物理地址是一个16位的二进制数,物理地址通常采用16进制书写。
16位CPU内部拥有20根地址线,它的寻址范围就是2的20次方,也就是1M的内存空间。
但是16位CPU存放存储单元偏移量的寄存器(IP,SP,BP,SI,DI,BX)的编码范围仅为:00000H - 0FFFFH,也就是只能访问65536个存储单元,64K。
为了能够访问1M的内存空间,CPU就采用了内存分段的管理模式,并且在CPU内部加入了段寄存器。
首先说的是段寄存器的大小是16位的,其中放的是段值。一个物理地址的计算是段值*段的大小+段内偏移=1M;而段内偏移的范围是地址线位数或者指针寄存器的大小决定的,所以它的范围是0-64K。当为0时也就是段的起始地址,所以此时段的大小最小为16.否则不能等于1M。所以我认为既然是为了用16位表示20位的地址空间而采用的分段,所以段的 起始地址肯定就是16的倍数了。
参考:80x86,完整的地址当初被设计为 段址*16+偏址,所以就要求段对齐在 16 的倍数上了。定为 16 应该是和当时内存容量的预期有关。这样的地址形成方式可以访问到 1M 的内存空间。
存储单元的物理地址是一个16位的二进制数,物理地址通常采用16进制书写。
16位CPU内部拥有20根地址线,它的寻址范围就是2的20次方,也就是1M的内存空间。
但是16位CPU存放存储单元偏移量的寄存器(IP,SP,BP,SI,DI,BX)的编码范围仅为:00000H - 0FFFFH,也就是只能访问65536个存储单元,64K。
为了能够访问1M的内存空间,CPU就采用了内存分段的管理模式,并且在CPU内部加入了段寄存器。
首先说的是段寄存器的大小是16位的,其中放的是段值。一个物理地址的计算是段值*段的大小+段内偏移=1M;而段内偏移的范围是地址线位数或者指针寄存器的大小决定的,所以它的范围是0-64K。当为0时也就是段的起始地址,所以此时段的大小最小为16.否则不能等于1M。所以我认为既然是为了用16位表示20位的地址空间而采用的分段,所以段的 起始地址肯定就是16的倍数了。
参考:80x86,完整的地址当初被设计为 段址*16+偏址,所以就要求段对齐在 16 的倍数上了。定为 16 应该是和当时内存容量的预期有关。这样的地址形成方式可以访问到 1M 的内存空间。
#4
DS:0x075A:0x0000
SS:0x075B:0x0000
CS:0x075B:0x0000
而且此处。内存分配是连续分配,也就说紧接着数据段后面就是栈段,紧接着栈段之后就是CS段,这样就可以起到保护作用,当数据访问越段时就需要格外当心,但是在段内就可随意访问了
SS:0x075B:0x0000
CS:0x075B:0x0000
而且此处。内存分配是连续分配,也就说紧接着数据段后面就是栈段,紧接着栈段之后就是CS段,这样就可以起到保护作用,当数据访问越段时就需要格外当心,但是在段内就可随意访问了
#5
建议研究一下DOS加载.COM或.EXE对应的汇编代码。
#1
经过我的研究,发现上面的研究过程有点小问题。
首先,ss在后面有个赋值,我没有执行到那一步去看。
再者忘记了在程序内存中,还有PSP这么个特别的东西。
整理了一下,在我的模拟环境中,上面程序,执行到最后,有如下内存结构分布。
所以说,可见,ss最后和stack是一致的,ds+10h(psp长度)= data,cs = code
但是我又想到,这里的cs与code的相等并未明确赋值,而ss,ds都有对应的mov语句将他们改动到了stack,data上,
所以我想知道,stack实际指向的是什么?data指向什么?code应该是和cs一样的吧。
首先,ss在后面有个赋值,我没有执行到那一步去看。
再者忘记了在程序内存中,还有PSP这么个特别的东西。
整理了一下,在我的模拟环境中,上面程序,执行到最后,有如下内存结构分布。
所以说,可见,ss最后和stack是一致的,ds+10h(psp长度)= data,cs = code
但是我又想到,这里的cs与code的相等并未明确赋值,而ss,ds都有对应的mov语句将他们改动到了stack,data上,
所以我想知道,stack实际指向的是什么?data指向什么?code应该是和cs一样的吧。
#2
对 .exe 类的来说,程序刚载入时,CS:IP 指向你程序的入口;SS:SP,如果你的堆栈段定义用了 STACK 修饰(mystack segment
stack),则也会指向到你的栈;DS 和 ES 则是指向 PSP,后面指向哪里需要你自己的代码来做。
#3
计算机的内存管理单元是以“字节”为最小单位进行线性编址的,字节是80x86CPU对内存管理的基元。为了标识每个存储单元,就给每个存储单元规定一个编号,该编号就是内存单元的物理地址。
存储单元的物理地址是一个16位的二进制数,物理地址通常采用16进制书写。
16位CPU内部拥有20根地址线,它的寻址范围就是2的20次方,也就是1M的内存空间。
但是16位CPU存放存储单元偏移量的寄存器(IP,SP,BP,SI,DI,BX)的编码范围仅为:00000H - 0FFFFH,也就是只能访问65536个存储单元,64K。
为了能够访问1M的内存空间,CPU就采用了内存分段的管理模式,并且在CPU内部加入了段寄存器。
首先说的是段寄存器的大小是16位的,其中放的是段值。一个物理地址的计算是段值*段的大小+段内偏移=1M;而段内偏移的范围是地址线位数或者指针寄存器的大小决定的,所以它的范围是0-64K。当为0时也就是段的起始地址,所以此时段的大小最小为16.否则不能等于1M。所以我认为既然是为了用16位表示20位的地址空间而采用的分段,所以段的 起始地址肯定就是16的倍数了。
参考:80x86,完整的地址当初被设计为 段址*16+偏址,所以就要求段对齐在 16 的倍数上了。定为 16 应该是和当时内存容量的预期有关。这样的地址形成方式可以访问到 1M 的内存空间。
存储单元的物理地址是一个16位的二进制数,物理地址通常采用16进制书写。
16位CPU内部拥有20根地址线,它的寻址范围就是2的20次方,也就是1M的内存空间。
但是16位CPU存放存储单元偏移量的寄存器(IP,SP,BP,SI,DI,BX)的编码范围仅为:00000H - 0FFFFH,也就是只能访问65536个存储单元,64K。
为了能够访问1M的内存空间,CPU就采用了内存分段的管理模式,并且在CPU内部加入了段寄存器。
首先说的是段寄存器的大小是16位的,其中放的是段值。一个物理地址的计算是段值*段的大小+段内偏移=1M;而段内偏移的范围是地址线位数或者指针寄存器的大小决定的,所以它的范围是0-64K。当为0时也就是段的起始地址,所以此时段的大小最小为16.否则不能等于1M。所以我认为既然是为了用16位表示20位的地址空间而采用的分段,所以段的 起始地址肯定就是16的倍数了。
参考:80x86,完整的地址当初被设计为 段址*16+偏址,所以就要求段对齐在 16 的倍数上了。定为 16 应该是和当时内存容量的预期有关。这样的地址形成方式可以访问到 1M 的内存空间。
#4
DS:0x075A:0x0000
SS:0x075B:0x0000
CS:0x075B:0x0000
而且此处。内存分配是连续分配,也就说紧接着数据段后面就是栈段,紧接着栈段之后就是CS段,这样就可以起到保护作用,当数据访问越段时就需要格外当心,但是在段内就可随意访问了
SS:0x075B:0x0000
CS:0x075B:0x0000
而且此处。内存分配是连续分配,也就说紧接着数据段后面就是栈段,紧接着栈段之后就是CS段,这样就可以起到保护作用,当数据访问越段时就需要格外当心,但是在段内就可随意访问了
#5
建议研究一下DOS加载.COM或.EXE对应的汇编代码。