2

我已经开始学习组装了。我遇到了这些线。

;*************************************************;
; Second Stage Loader Entry Point
;************************************************;

main:
   cli  ; clear interrupts
   push cs ; Insure DS=CS
   pop ds

在第二行代码中,代码段被推送到堆栈(我认为是这个)。我在很多代码中都看到过。为什么我们应该这样做以及它如何确保 DS =CS?在第三行 DS 是从堆栈中弹出的(我认为这个)。为什么要完成?它从堆栈中弹出意味着它之前被推入堆栈。没有代码。任何人都可以向我解释这一切吗?提前致谢。

4

5 回答 5

4

cs并且ds只是寄存器,很像占位符/变量,有关寄存器的更多信息请在此处阅读。在第二行,您说push cs这意味着您将 的内容放入cs堆栈,然后在下一行将pop其放回ds.

所以刚刚发生的事情是你复制csds.

push是一条指令,上面写着“把它放在堆栈的顶部”

pop是一条指令,上面写着“从堆栈中取出顶部值”

一旦你做了一个pop值就不再存储在堆栈中。

于 2010-11-05T06:59:56.383 回答
4

push cs确保这一点的不是那个,而是push cs; pop ds;组合。

第一条指令将 的当前值复制cs到堆栈上,第二条指令将该值从堆栈中拉出并将其放入ds寄存器。


为了响应您对更多信息的请求,让我们从以下堆栈和寄存器开始:

stack=[1,2,3], cs=7, ds=6

After push cs,它将cs寄存器的值压入堆栈:

stack=[1,2,3,7], cs=7, ds=6

After pop ds,它从堆栈中弹出一个值并将其放入ds寄存器:

stack=[1,2,3], cs=7, ds=7

基本上就是这样。


我不记得是否可以使用mov指令在段寄存器之间传输(我不认为是,但我可能错了,这将需要推/弹出序列)。该链接似乎可以确认:没有mov将段寄存器作为源目标的选项。

但即使是这样,汇编程序编码人员也经常选择更合适的指令,无论是为了速度还是紧凑代码(或两者兼而有之),例如使用xor ax, ax而不是mov ax, 0例如。

于 2010-11-05T06:58:55.553 回答
1

“将此寄存器压入堆栈,将堆栈弹出至此寄存器”有时可以使用 MOV 指令完成,例如 MOV ax,dx。但是指令集中没有一些寄存器到寄存器的 MOV 指令,并且 IIRC MOV ds,cs 不可用。这可能是将其放入内存(嗯,缓存,真的)并读回它的原因。

于 2010-11-05T07:29:24.867 回答
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)弹出DS

CS has value X
DS has value X
Stack has ....

但是什么是段寄存器。在过去,8086 有 16 位地址寄存器,但有 20 位地址空间。因此,他们使用段寄存器通过将段寄存器乘以 16 将两者组合到 20 位空间,并添加内存位置。为了节省空间,我们有近指针(没有在段内跳转的段)和远指针(有段)。

随着 80286 保护模式的引入,段寄存器被重新用作段描述符。他们指向一个内存位置,该位置提供了足够的信息以到达真实空间。但是现在我们有了线性地址空间(虚拟映射到真实内存上)。

于 2010-11-05T06:59:52.397 回答
0

就像在评论中写的一样,push cs然后pop ds确保ds=cs?. push cs将 cs 的值放在栈顶,然后pop ds从栈中取出该值并将其存储在ds.

于 2010-11-05T07:00:53.107 回答