at&t写x86启动代码遇到问题(请教高手)

时间:2021-01-27 03:45:10
这是一段模式跳转入保护模式的代码,
BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17

.code16
.align 2
.text
.globl _start
_start:
ljmp $BOOTSEG, $go
go: movw %cs,%ax
movw %ax,%ds
movw %ax,%ss
movw $0x0400, %sp

load_system:
xorw %dx, %dx # drive 0, head 0
movw $0x02, %cx # sector 2, track 0
movw $SYSSEG, %ax # load kernel at es:bx(0x1000:0x0000)
movw %ax, %es
xorw %bx, %bx
movb $0x02, %ah # service 2,"read sector(s)"
movb $SYSLEN, %al # kernel is at most 17 sectors
int $0x13 
jnc ok_load
die: jmp die #error,then die

# move kernel to 0x0000, total 
ok_load:
cli
movw $SYSSEG, %ax #move kernel from ds:si to es:di
movw %ax, %ds #total 4KB
xorw %si, %si
xorw %ax, %ax #es:di
movw %ax, %es
xorw %di, %di
movw $0x1000, %cx
cld
rep movsw

movw $BOOTSEG, %ax #ds(0x7c00)
movw %ax, %ds
lidt idt_48 #load idt
lgdt gdt_48  #load gdt

movw $0x0001, %ax
lmsw %ax
ljmp $8, $0

gdt: .quad 0x0 #NULL
.quad 0x00c09a00000007ff #0x08 code section limit=2047*4K,
.quad 0x00c09200000007ff #0x10 data section  D/B=1,P=1,TYPE=A,
.quad 0x00c0920b80000002 #0x18 video memory

gdt_48: .word 0x03f #gdt limit=8(item)*8B=64B,
.word 0x7c00+gdt,0
idt_48: .word 0 #idt limit=0
.word 0,0

.org 510
.word 0xaa55
-------------------------------------------------------------
这是makefile命令:
boot: boot.s
as -o boot.o boot.s
ld -s -x -M -o boot boot.o >boot.map
---------------------------------------------------==
执行make 遇到ld提示:
boot.o(.text+0x1);In function '_start':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x40);In function 'ok_load':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x45);In function 'ok_load':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x74);In function 'gdt_48':
:relocation truncated to fit : R_386_16 .text
-----------------------------------------------------
1。请问是什么原因,我推测是as编译成了16位代码,然而地址标号是32位的地址,所以连接的时候出现了问题,请问如何解决?
2。反汇编后,成了这种状态,我推测是因为objdump 只识别32位代码,所以16位的代码反编译后就出现了混乱状态,请问高手到底是因为什么?
boot.o:     file format elf32-i386

Disassembly of section .text:

00000000 <_start>:
   0: ea 05 00 c0 07 8c c8  ljmp   $0xc88c,$0x7c00005

00000005 <go>:
   5: 8c c8                 mov    %cs,%eax
   7: 8e d8                 mov    %eax,%ds
   9: 8e d0                 mov    %eax,%ss
   b: bc 00 04 31 d2        mov    $0xd2310400,%esp

0000000e <load_system>:
   e: 31 d2                 xor    %edx,%edx
  10: b9 02 00 b8 00        mov    $0xb80002,%ecx
  15: 10 8e c0 31 db b4     adc    %cl,0xb4db31c0(%esi)
  1b: 02 b0 11 cd 13 73     add    0x7313cd11(%eax),%dh
  21: 02 eb                 add    %bl,%ch
……



30 个解决方案

#1


也不说出现了什么问题?
我也正在写相同的东西,不过我这边运行很正常啊。

#2


不好意思,看错了,我继续看你的东西

#3


在最前面加上
.code16

#4


change this
 
BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17

.code16
.align 2
.text
.globl _start

To

.code16
.align 2
.text
.globl _start

BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17

#5


不行啊,依然有问题, linux内核2.4版也没有把.code16放最初
继续请教ing

#6


你试一次先吧
我试过是可以的

#7


刚式了,真的不行,还是原来的错误

#8


.code16
.text
.global _start
_start:
     movw $0,%ax
.fill 510-.
.word 0xaa55
我这样编译没问题

as -o bootsect.o bootsect.S
ld -o bootsect bootsect.o

#9


对这样肯定是没有问题的,因为其中没有地址标号
 请看我贴的ld提示,
原因是在于我代码里面有标号,然而标号很可能不受.code16影响,依然是32位的,如果仅仅是截断了高16位.也就算了,因为没有什么影响,但是问题在于,这写错误直接映像生成可执行文件

#10



.code16
.align 2
.text
.globl _start

BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17

_start:
ljmp$BOOTSEG, $go
go:movw%cs,%ax
movw%ax,%ds
movw%ax,%ss
movw$0x0400, %sp

load_system:
xorw%dx, %dx# drive 0, head 0
movw$0x02, %cx# sector 2, track 0
movw$SYSSEG, %ax# load kernel at es:bx(0x1000:0x0000)
movw%ax, %es
xorw%bx, %bx
movb$0x02, %ah# service 2,"read sector(s)"
movb$SYSLEN, %al# kernel is at most 17 sectors
int$0x13
jncok_load
die:jmpdie#error,then die

# move kernel to 0x0000, total
ok_load:
cli
movw$SYSSEG, %ax#move kernel from ds:si to es:di
movw%ax, %ds#total 4KB
xorw%si, %si
xorw%ax, %ax#es:di
movw%ax, %es
xorw%di, %di
movw$0x1000, %cx
cld
repmovsw

movw$BOOTSEG, %ax#ds(0x7c00)
movw%ax, %ds
lidtidt_48#load idt
lgdtgdt_48 #load gdt

movw$0x0001, %ax
lmsw%ax
ljmp$8, $0

gdt:.quad0x0#NULL
.quad0x00c09a00000007ff#0x08 code section limit=2047*4K,
.quad0x00c09200000007ff#0x10 data section D/B=1,P=1,TYPE=A,
.quad0x00c0920b80000002#0x18 video memory

gdt_48:.word0x03f#gdt limit=8(item)*8B=64B,
.word0x7c00+gdt,0
idt_48:.word0#idt limit=0
.word0,0

.org 510
.word0xaa55

我就是编到,你是甚麽问题呀?

#11


我就是可以成功compile.
不要用objdump吧, 在object file, address是不确定的, because haven't linked.
用ndisasm去反汇编吧,

#12


就是出现了以下提示然后就不能生成可执行文件了,顺便说,我是在虚拟机上运行的

执行make 遇到ld提示:
boot.o(.text+0x1);In function '_start':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x40);In function 'ok_load':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x45);In function 'ok_load':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x74);In function 'gdt_48':
:relocation truncated to fit : R_386_16 .text
make :***(boot) error 1

#13


ndisasm刚用了,出现一堆不对头的指令,估计把文件头部也给算进去了

#14


我没办法把你的文件,赋值到我的远程登陆的LInux主机上,没法完全试试,但是我觉得应该没什么问题,你的as是什么版本的?

#15


ld是什么版本的?

#16


我建议用LD脚本编译吧,不要用默认的方式编译,你这样编译了也运行不了。

#17



我把。code16
去掉依然make一下只出现了一个ld错误提示
boot.o(.text+0x8a);In function 'gdt_48':
:relocation truncated to fit : R_386_16 .text

问题出在对应代码:
gdt:.quad0x0#NULL
.quad0x00c09a00000007ff#0x08 code section limit=2047*4K,
.quad0x00c09200000007ff#0x10 data section  D/B=1,P=1,TYPE=A,
.quad0x00c0920b80000002#0x18 video memory

gdt_48:.word0x03f#gdt limit=8(item)*8B=64B,
.word0x7c00+gdt,0                         #此行gdt标号是32位的会被截断

反汇编对应代码:

00000068 <gdt>:
...
  70: ff 07                 incl   (%edi)
  72: 00 00                 add    %al,(%eax)
  74: 00 9a c0 00 ff 07     add    %bl,0x7ff00c0(%edx)
  7a: 00 00                 add    %al,(%eax)
  7c: 00 92 c0 00 02 00     add    %dl,0x200c0(%edx)
  82: 00 80 0b 92 c0 00     add    %al,0xc0920b(%eax)

00000088 <gdt_48>:
  88: 3f                    aas    
  89: 00 68 7c              add    %ch,0x7c(%ea)
恳请高手继续指教,这个小问题把我卡住几天了,但是我不想放弃它。

#18


ld version 2.13.90.0.18
as version 2.13.90.0.18

#19


用一段脚本:
OUTPUT_FORMAT("binary")
INPUT(boot.o)
ENTRT(_start)
SECTIONS
{
  .text : { *(.text) }
}

ld -T boot.script -M

#20


不加.code16是肯定不能运行的。

#21


show me your file again?

#22


如果我行但你不行,好明显是你的as有问题.
给我看看你跟足我做的那个file

#23


唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉


你这一句根本compile出来的不是object file:
as -o boot.o boot.s

你打:
file boot.o
就知它原来是Coff executable


唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉

#24


非常感谢
这就是跟你改的程序
.code16
.align 2
.text
.globl _start

BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17


_start:



ljmp $BOOTSEG, $go
go: movw %cs,%ax
movw %ax,%ds
movw %ax,%ss
movw $0x0400, %sp

load_system:
xorw %dx, %dx # drive 0, head 0
movw $0x02, %cx # sector 2, track 0
movw $SYSSEG, %ax # load kernel at es:bx(0x1000:0x0000)
movw %ax, %es
xorw %bx, %bx
movb $0x02, %ah # service 2,"read sector(s)"
movb $SYSLEN, %al # kernel is at most 17 sectors
int $0x13 
jnc ok_load
die: jmp die #error,then die

# move kernel to 0x0000, total 
ok_load:
cli
movw $SYSSEG, %ax #move kernel from ds:si to es:di
movw %ax, %ds #total 4KB
xorw %si, %si
xorw %ax, %ax #es:di
movw %ax, %es
xorw %di, %di
movw $0x1000, %cx
cld
rep movsw

movw $BOOTSEG, %ax #ds(0x7c00)
movw %ax, %ds
lidt idt_48 #load idt
lgdt gdt_48  #load gdt

movw $0x0001, %ax
lmsw %ax
ljmp $8, $0

gdt: .quad 0x0 #NULL
.quad 0x00c09a00000007ff #0x08 code section limit=2047*4K,
.quad 0x00c09200000007ff #0x10 data section  D/B=1,P=1,TYPE=A,
.quad 0x00c0920b80000002 #0x18 video memory

gdt_48: .word 0x03f #gdt limit=8(item)*8B=64B,
.word 0x7c00+gdt,0
idt_48: .word 0 #idt limit=0
.word 0,0

.org 510
.word 0xaa55

#25


我刚才file boot.o
显示的是ELF 32-bit

#26


ELF 32-bit是不能当bootloader执行的。

#27


该回复被版主删除

#28


i have sms you , please check

#29


你这样做就可以了

as -o boot.o boot.asm
objcopy -O binary boot.o output.bin

#30


i have answered you
http://community.csdn.net/Expert/TopicView3.asp?id=5018881

#1


也不说出现了什么问题?
我也正在写相同的东西,不过我这边运行很正常啊。

#2


不好意思,看错了,我继续看你的东西

#3


在最前面加上
.code16

#4


change this
 
BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17

.code16
.align 2
.text
.globl _start

To

.code16
.align 2
.text
.globl _start

BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17

#5


不行啊,依然有问题, linux内核2.4版也没有把.code16放最初
继续请教ing

#6


你试一次先吧
我试过是可以的

#7


刚式了,真的不行,还是原来的错误

#8


.code16
.text
.global _start
_start:
     movw $0,%ax
.fill 510-.
.word 0xaa55
我这样编译没问题

as -o bootsect.o bootsect.S
ld -o bootsect bootsect.o

#9


对这样肯定是没有问题的,因为其中没有地址标号
 请看我贴的ld提示,
原因是在于我代码里面有标号,然而标号很可能不受.code16影响,依然是32位的,如果仅仅是截断了高16位.也就算了,因为没有什么影响,但是问题在于,这写错误直接映像生成可执行文件

#10



.code16
.align 2
.text
.globl _start

BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17

_start:
ljmp$BOOTSEG, $go
go:movw%cs,%ax
movw%ax,%ds
movw%ax,%ss
movw$0x0400, %sp

load_system:
xorw%dx, %dx# drive 0, head 0
movw$0x02, %cx# sector 2, track 0
movw$SYSSEG, %ax# load kernel at es:bx(0x1000:0x0000)
movw%ax, %es
xorw%bx, %bx
movb$0x02, %ah# service 2,"read sector(s)"
movb$SYSLEN, %al# kernel is at most 17 sectors
int$0x13
jncok_load
die:jmpdie#error,then die

# move kernel to 0x0000, total
ok_load:
cli
movw$SYSSEG, %ax#move kernel from ds:si to es:di
movw%ax, %ds#total 4KB
xorw%si, %si
xorw%ax, %ax#es:di
movw%ax, %es
xorw%di, %di
movw$0x1000, %cx
cld
repmovsw

movw$BOOTSEG, %ax#ds(0x7c00)
movw%ax, %ds
lidtidt_48#load idt
lgdtgdt_48 #load gdt

movw$0x0001, %ax
lmsw%ax
ljmp$8, $0

gdt:.quad0x0#NULL
.quad0x00c09a00000007ff#0x08 code section limit=2047*4K,
.quad0x00c09200000007ff#0x10 data section D/B=1,P=1,TYPE=A,
.quad0x00c0920b80000002#0x18 video memory

gdt_48:.word0x03f#gdt limit=8(item)*8B=64B,
.word0x7c00+gdt,0
idt_48:.word0#idt limit=0
.word0,0

.org 510
.word0xaa55

我就是编到,你是甚麽问题呀?

#11


我就是可以成功compile.
不要用objdump吧, 在object file, address是不确定的, because haven't linked.
用ndisasm去反汇编吧,

#12


就是出现了以下提示然后就不能生成可执行文件了,顺便说,我是在虚拟机上运行的

执行make 遇到ld提示:
boot.o(.text+0x1);In function '_start':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x40);In function 'ok_load':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x45);In function 'ok_load':
:relocation truncated to fit : R_386_16 .text
boot.o(.text+0x74);In function 'gdt_48':
:relocation truncated to fit : R_386_16 .text
make :***(boot) error 1

#13


ndisasm刚用了,出现一堆不对头的指令,估计把文件头部也给算进去了

#14


我没办法把你的文件,赋值到我的远程登陆的LInux主机上,没法完全试试,但是我觉得应该没什么问题,你的as是什么版本的?

#15


ld是什么版本的?

#16


我建议用LD脚本编译吧,不要用默认的方式编译,你这样编译了也运行不了。

#17



我把。code16
去掉依然make一下只出现了一个ld错误提示
boot.o(.text+0x8a);In function 'gdt_48':
:relocation truncated to fit : R_386_16 .text

问题出在对应代码:
gdt:.quad0x0#NULL
.quad0x00c09a00000007ff#0x08 code section limit=2047*4K,
.quad0x00c09200000007ff#0x10 data section  D/B=1,P=1,TYPE=A,
.quad0x00c0920b80000002#0x18 video memory

gdt_48:.word0x03f#gdt limit=8(item)*8B=64B,
.word0x7c00+gdt,0                         #此行gdt标号是32位的会被截断

反汇编对应代码:

00000068 <gdt>:
...
  70: ff 07                 incl   (%edi)
  72: 00 00                 add    %al,(%eax)
  74: 00 9a c0 00 ff 07     add    %bl,0x7ff00c0(%edx)
  7a: 00 00                 add    %al,(%eax)
  7c: 00 92 c0 00 02 00     add    %dl,0x200c0(%edx)
  82: 00 80 0b 92 c0 00     add    %al,0xc0920b(%eax)

00000088 <gdt_48>:
  88: 3f                    aas    
  89: 00 68 7c              add    %ch,0x7c(%ea)
恳请高手继续指教,这个小问题把我卡住几天了,但是我不想放弃它。

#18


ld version 2.13.90.0.18
as version 2.13.90.0.18

#19


用一段脚本:
OUTPUT_FORMAT("binary")
INPUT(boot.o)
ENTRT(_start)
SECTIONS
{
  .text : { *(.text) }
}

ld -T boot.script -M

#20


不加.code16是肯定不能运行的。

#21


show me your file again?

#22


如果我行但你不行,好明显是你的as有问题.
给我看看你跟足我做的那个file

#23


唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉


你这一句根本compile出来的不是object file:
as -o boot.o boot.s

你打:
file boot.o
就知它原来是Coff executable


唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉唉

#24


非常感谢
这就是跟你改的程序
.code16
.align 2
.text
.globl _start

BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17


_start:



ljmp $BOOTSEG, $go
go: movw %cs,%ax
movw %ax,%ds
movw %ax,%ss
movw $0x0400, %sp

load_system:
xorw %dx, %dx # drive 0, head 0
movw $0x02, %cx # sector 2, track 0
movw $SYSSEG, %ax # load kernel at es:bx(0x1000:0x0000)
movw %ax, %es
xorw %bx, %bx
movb $0x02, %ah # service 2,"read sector(s)"
movb $SYSLEN, %al # kernel is at most 17 sectors
int $0x13 
jnc ok_load
die: jmp die #error,then die

# move kernel to 0x0000, total 
ok_load:
cli
movw $SYSSEG, %ax #move kernel from ds:si to es:di
movw %ax, %ds #total 4KB
xorw %si, %si
xorw %ax, %ax #es:di
movw %ax, %es
xorw %di, %di
movw $0x1000, %cx
cld
rep movsw

movw $BOOTSEG, %ax #ds(0x7c00)
movw %ax, %ds
lidt idt_48 #load idt
lgdt gdt_48  #load gdt

movw $0x0001, %ax
lmsw %ax
ljmp $8, $0

gdt: .quad 0x0 #NULL
.quad 0x00c09a00000007ff #0x08 code section limit=2047*4K,
.quad 0x00c09200000007ff #0x10 data section  D/B=1,P=1,TYPE=A,
.quad 0x00c0920b80000002 #0x18 video memory

gdt_48: .word 0x03f #gdt limit=8(item)*8B=64B,
.word 0x7c00+gdt,0
idt_48: .word 0 #idt limit=0
.word 0,0

.org 510
.word 0xaa55

#25


我刚才file boot.o
显示的是ELF 32-bit

#26


ELF 32-bit是不能当bootloader执行的。

#27


该回复被版主删除

#28


i have sms you , please check

#29


你这样做就可以了

as -o boot.o boot.asm
objcopy -O binary boot.o output.bin

#30


i have answered you
http://community.csdn.net/Expert/TopicView3.asp?id=5018881