我已经开始学习装配。我遇到过这些问题。
;*************************************************;
; Second Stage Loader Entry Point
;************************************************;
main:
cli ; clear interrupts
push cs ; Insure DS=CS
pop ds
这里在第二行代码中,代码段被推送到堆栈(我想这个)。我在许多代码中看到过它。为什么我们应该这样做以及它如何确保DS = CS?在第三行DS弹出堆栈(我想这个)。为什么这样做?它是弹出堆栈意味着它是之前推送堆栈。没有代码。任何人都可以向我解释这一切吗?提前谢谢。
答案 0 :(得分:4)
push cs
不是确保这一点,而是push cs; pop ds;
组合。
第一条指令将cs
的当前值复制到堆栈中,第二条指令将该值从堆栈中拉出并将其放入ds
寄存器。
为了回应您的更多信息请求,让我们从以下堆栈开始注册并注册:
stack=[1,2,3], cs=7, ds=6
在push cs
之后,它将cs
寄存器的值压入堆栈:
stack=[1,2,3,7], cs=7, ds=6
在pop ds
之后,从堆栈中弹出一个值并将其放入ds
寄存器中:
stack=[1,2,3], cs=7, ds=7
基本上就是这样。
我无法回想起我是否有可能通过mov
指令在段寄存器之间进行传输(我认为不是,但我可能错了,这将是必要的推/弹顺序)。这个link似乎证实:没有mov
选项,段注册为源和目的地。
但即便如此,汇编程序编码人员也经常选择更合适的指令,无论是速度代码还是紧凑代码(或两者兼而有之),例如使用xor ax, ax
而不是mov ax, 0
。
答案 1 :(得分:4)
cs
和ds
只是寄存器,非常类似占位符/变量,用于更多information about registers read here。在第二行,您说push cs
这意味着您将cs
的内容放入堆栈,然后将pop
的内容重新放回ds
。
刚刚发生的事情是您将cs
复制到ds
。
push
是一条说“把它置于堆栈顶部”的指令
pop
是一条说“从堆栈中取出最高值”的指令
执行pop
后,该值不再存储在堆栈中。
答案 2 :(得分:1)
'将此寄存器压入堆栈,弹出堆栈到此寄存器'有时可以使用MOV指令完成,例如MOV ax,dx。但是指令集中没有一些寄存器到寄存器的MOV指令,并且IIRC MOV ds,cs不可用。这可能是将它放入内存(好吧,缓存,真的)并将其读回来的原因。
答案 3 :(得分:0)
通过将CS的值推入堆栈并将其弹出到DS中,可以确保DS具有与CS相同的值。
我没有在汇编程序中编程一段时间,但我认为没有直接的方法可以从一个段寄存器转移到另一个段寄存器。
您可以将堆栈视为一堆数据。你把东西推到顶部,然后它就会停留在那里,直到你弹出它。通过这种方式,您可以使用堆栈来交换数据。但是大多数时候你用它来保存数据,这样你就可以将寄存器用于其他目的,并在以后恢复内容。
执行代码时会发生这种情况。
1)初始情况
CS has value X
DS has value Y
Stack has ....
2)推CS
CS has value X
DS has value Y
Stack has ...., X
3)pop DS
CS has value X
DS has value X
Stack has ....
但什么是段寄存器。 在过去,8086有16位地址寄存器但有20位地址空间。因此,他们使用段寄存器通过将段寄存器乘以16将两者合并到20位空间,并添加存储器位置。为了节省空间,我们有近指针(没有段在段内跳跃)和远指针(带段)。
随着80286保护模式的引入,段寄存器被重用为段描述符。他们指出了一个内存位置,它提供了足够的信息来进入真实空间。但现在我们有了线性地址空间(实际上映射在实际内存上)。
答案 4 :(得分:0)
与撰写的评论一样,push cs
然后pop ds
确保ds=cs?
。 push cs
将cs的值放在堆栈的顶部,然后pop ds
从堆栈中删除值并将其存储在ds
中。