boot.s head.s 学习说明

Linux内核——多任务内核程序head.s 源码详解 Linux 0.00 head.s 阅读详情
<pre name="code" class="plain">!	boot.s
!
! It then loads the system at 0x10000, using BIOS interrupts. Thereafter
! it disables all interrupts, changes to protected mode, and calls the 
!计算机在启动的时候会把磁盘里的第一个扇区的内容存到内存中0x7c00这个位置上
!这个时候计算机用的是实地址模式BOOTSET=0x07c0的原因是因为它是段地址,要左
!左移一位就变成了0x7c00了
BOOTSEG = 0x07c0
!引导程序的目的是把head.s编译出来的代码(二进制文件)先放到0x10000处,
!这里用SYSSEG=0x1000是因为这属于段地址,需要在十六进制下左移一位再加上偏
!地址。
SYSSEG  = 0x1000			! system loaded at 0x10000 
!内核所占用的扇区数,每个扇区是512Byte,这个不是真正内核的大小,而是内核
!大小的一个上限。SYSLEN  = 17				! sectors occupied.

entry start
start:
        !跳到go的地方,并且将BOOTSEG作为段地址,go表示的是偏移地址,go表示
        !的是go所在的指令地址到程序开始地址的距离,然后加上BOOTSEG这个段
        !地址后才能找到真正的地址,起初的cs=0,eip=0x7c00,如果直接执行下
        !去的话就变成cs=0,eip=0x7c05了,但是用了这句jmpi后就变成cs=0x07c0
        !eip=0x5了,主要是为了初始化cs,eip这两个寄存器。
	jmpi	go,#BOOTSEG             
        !通过ax将数据段寄存器赋值,和cs一样,因为这段代码的指令和数据是混
        !合在一起的。
go:	mov	ax,cs
	mov	ds,ax
        !将堆栈段寄存器ss也设置的和cs一样,同时将堆栈偏移地址sp中设成0x400
        !0x400转换成十进制为1024,也就是说在第1024字节处,这个地址要大于
        !512很多,因为IA-32的架构下堆栈是倒着长的
	mov	ss,ax
	mov	sp,#0x400		! arbitrary value >>512

! ok, we've written the message, now
load_system:
        !load_system这段代码是为了加载head.s
        !dx cx 是为了告诉系统一些拷贝代码的参数
        !dh=0x00 磁头号 dl=0x00 驱动器号 
        !cl(7:6)=00B 磁道号高2位 ch=0x00 磁道号低8位 组合出来磁道号也是0
        !cl(5:0)=00010B 表示起始扇区号,扇区号从1开始算,前面第一个扇区就
        !是boot.s也就是这份代码,紧接着从第二个扇区开始的就是head.s了
	mov	dx,#0x0000
	mov	cx,#0x0002
        !es:bx 也是一组段地址加偏移地址表示地址的组合表示写入的起始位置
        !为了把代码先复制到0x10000处,因此通过ax把SYSSEG=0X1000作为段地址
        !放到es中,然后xor bx,bx将bx清零,从而组合成0x10000的地址
	mov	ax,#SYSSEG
	mov	es,ax
	xor	bx,bx
        !ax也是作为一个传递参数的寄存器需要设置的
        !ah 表示后面int 0x13系统中断需要执行的操作是从磁盘复制代码到内存
        !al则是需要写的字节数,这个只可大于head.s的长度,保证代码完整
	mov	ax,#0x200+SYSLEN
	int 	0x13
        !如果拷贝完成的话就跳到ok_load段,否则此处陷入死循环
	jnc	ok_load
die:	jmp	die

! now we want to move to protected mode ...
!这段代码将会把代码从0x10000移到0x0处,之所以不能直接把代码移到0x0处
!是因为计算机启动的时候会把bios的代码存到开头,比如int 0x13的代码,如果
!在复制的过程中把代码覆盖过去的话系统就出错了,因此把它放到内存0x10000处
!后在用cpu的指令把代码挪到0x0
ok_load:
        !关闭中断
	cli			! no interrupts allowed !
        !移动需要源地址ds:si 目的地址 es:di
        !通过ax把head.s代码的段地址0x1000放到数据段ds中
        !将0x0送到es中,最后将si和di都变成0
        !和loop一样cx表示循环次数,每次都自减1,0x2000=8K次(1K=2^10)
	mov	ax, #SYSSEG
	mov	ds, ax
	xor	ax, ax
	mov	es, ax
	mov	cx, #0x2000
	sub	si,si
	sub	di,di
        !rep表示重复下面的代码知道cx变成0
        !movw 中mov表示他是一个移动指令,就是将ds:si 移到 es:di处
        !w表示每次移动一个字,每复制一次si和di就自动+1
        !但是为什么移动的代码段明显大于head.s
        !我现在能给出的解释就是为了保险起见,多复制总比少复制好
        !但是在从磁盘中选定的长度是17个扇区 也就是相当于8704bytes
        !而这里移动的次数相当于16384bytes,这两个不相等也是醉了。
	rep
	movw
        !将ds恢复过来
	mov	ax, #BOOTSEG
	mov	ds, ax
        !lidt 将idt的基地址和限制长度载入到idtr中
        !lgdt 将gdt的基地址和限制长度载入到gdtr中,这边可以先下去看
        ! idt_48 和gdt_48的内容
	lidt	idt_48		! load idt with 0,0
	lgdt	gdt_48		! load gdt with whatever appropriate

! absolute address 0x00000, in 32-bit protected mode.
        !设置机器状态字,开启保护模式
	mov	ax,#0x0001	! protected mode (PE) bit
	lmsw	ax		! This is it!
        !保护模式开启后 jmpi 偏移地址,段地址就和前面的使用方法不一样
        !这里的段地址不再左移变成基地址,而是要从gdt表中取出基地址
        !而后再加上偏移地址0,执行后的结果就是eip变成0,cs变成用8
        !从gdt中取出的段地址了,这里可以看gdt表
        !gdt表每4个字作为一项段描述符,从0开始计,但第0项无用,上面8是选择
        !符也就是1000B,是4个字节,共32位,低16位有用,15:3 是索引,表示
        !gdt表中的第几项,这里可以看到cs(15:3)是1B,表示第一项
        !第0位为1表示执行程序以外的事件造成了异常(不明白什么意思???)
        !第1位为1表示这是指向idt的
        !第2位为1表示这是指向ldt的
        !可见这三位都是0
        !因此8表示gdt表中的第一项
	jmpi	0,8		! jmp offset 0 of segment 8 (cs)

!gdt表中的每项是4个字即64位
!查询一下数据段描述符 代码段描述符 系统段描述符
!这里用第一项为例子,我们先从中间找到段限长,也就最低字0x07ff中的0x07ff
!然后我们再拼出基地址,倒数第二低字节0x0000就是基地址的低16位,第二高字节
!0x9A00的低8位0x0 是基地址的23:16位,而最高字的最高8位就是基地址的高8位,
!至此我们可以完整地拼出了基地址0x0。
!剩下的就是最高双字的中间16位了,这里我们写出来
!C    0    9    A
!1100 0000 1001 1010 用23到8表示 中间19到16表示段限长的19:16位,这里得
!到了完整的段限长0x007ff 
gdt:	.word	0,0,0,0		! dummy

	.word	0x07FF		! 8Mb - limit=2047 (2048*4096=8Mb)
	.word	0x0000		! base address=0x00000
	.word	0x9A00		! code read/exec
	.word	0x00C0		! granularity=4096, 386

	.word	0x07FF		! 8Mb - limit=2047 (2048*4096=8Mb)
	.word	0x0000		! base address=0x00000
	.word	0x9200		! data read/write
	.word	0x00C0		! granularity=4096, 386
!这里可以看到这是两个部分的数据,idt_48有6个字节,最低位字节是 idt表的长度
!注意这个代码在上面的表示低位地址,高位的两个字节是idt的基地址,这里没写idt
!因此都默认成0,idt会在head.s中写出来,接着说字节问题,在书上画idtr的时候是
!从左到右是基地址 限制长度,地址从左到右是从高到低,而这里的代码是从下到
!上是对应的地址从高到低,因此有点违背常理,需要注意。
!gdt_48 可以看到0x7c00+gdt是上面gdt表的位置
idt_48: .word	0		! idt limit=0
	.word	0,0		! idt base=0L
gdt_48: .word	0x7ff		! gdt limit=2048, 256 GDT entries
	.word	0x7c00+gdt,0	! gdt base = 07xxx
.org 510
	.word   0xAA55



</pre><pre name="code" class="plain">
<pre name="code" class="plain">#  head.s contains the 32-bit startup code.
#  Two L3 task multitasking. The code of tasks are in kernel area,
#  just like the Linux. The kernel code is located at 0x10000.
.code32
!!!!!!需要注意的是这份代码的目的操作数和源操作数的放置顺序是反的。
!这里有许多选择符,来取各种表中的项,一会儿设置表的时候再回头看

SCRN_SEL	= 0x18
TSS0_SEL	= 0x20
LDT0_SEL	= 0x28
TSS1_SEL	= 0X30
LDT1_SEL	= 0x38
.global startup_32
.text
startup_32:
!通过ax将选择符0x10放到ds中,初始化数据段,0x10的低3位是000因此是在gdt表中
!的10B项,也就是第二项,而gdt表就是刚才boot.s中设置的,和第一项唯一的区别
!就是其中的A和C,这其中蕴含着数据段和代码段的属性区别
	movl $0x10,%eax
	mov %ax,%ds
!设置堆栈地址,转去init_stack代码,这里还包括了ss=ds
	lss init_stack,%esp

# setup base fields of descriptors.
!调用设置idt和gdt的过程,跳转
	call setup_idt
	call setup_gdt
!重新设置各个段寄存器,和初始化堆栈
	movl $0x10,%eax		
	mov %ax,%ds		
	mov %ax,%es
	mov %ax,%fs
	mov %ax,%gs
	lss init_stack,%esp

!设置计时器,定时产生中断
	movb $0x36, %al
	movl $0x43, %edx
	outb %al, %dx
	movl $11930, %eax        
	movl $0x40, %edx
	outb %al, %dx
	movb %ah, %al
	outb %al, %dx

!设置内核段选择符是0x8
	movl $0x00080000, %eax
!设置调用的代码是timer_interrupt
	movw $timer_interrupt, %ax
!设置一些属性
	movw $0x8E00, %dx
!系统的定时中断号是8,因此要用新的中断来覆盖它,下面就是把上面设置的写进去
	movl $0x08, %ecx             
	lea idt(,%ecx,8), %esi
	movl %eax,(%esi)
	movl %edx,4(%esi)
!再设置一个80中断来处理
!可见是调用system_interrupt来处理
	movw $system_interrupt, %ax
	movw $0xef00, %dx
	movl $0x80, %ecx
	lea idt(,%ecx,8), %esi
	movl %eax,(%esi)
	movl %edx,4(%esi)

# unmask the timer interrupt.
#	movl $0x21, %edx
#	inb %dx, %al
#	andb $0xfe, %al
#	outb %al, %dx

# Move to user mode (task 0)
!将标志寄存器压栈,然后在栈中把nt标志复位,完了之后弹出恢复
	pushfl
	andl $0xffffbfff, (%esp)
	popfl
!设置tr的选择符是0x20,tr寄存器中的值就是0x20
	movl $TSS0_SEL, %eax
	ltr %ax
!将ldt装载进寄存器
	movl $LDT0_SEL, %eax
	lldt %ax
!current表示当前的任务号是0
	movl $0, current
!打开中断
	sti
!通过压栈,回弹,实现跳转
!iret的回弹顺序是eip cs eflag esp ss,让初始化,然后指针指向了任务0
!0x17是一个选择符,二进制展开是00011111,可见是ldt中的第三项
	pushl $0x17
	pushl $init_stack
	pushfl
	pushl $0x0f
	pushl $task0
	iret

/****************************************/
setup_gdt:
	lgdt lgdt_opcode
	ret
!这里是把所有的idt都设成一样的,也就是当有中断来的时候就调用ignore_int过程
!0xb5
!这里终端门设置高双字是edx,低双字是eax
!movl表示每次移动双字
setup_idt:
	lea ignore_int,%edx
	movl $0x00080000,%eax
	movw %dx,%ax		/* selector = 0x0008 = cs */
	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */
	lea idt,%edi
	mov $256,%ecx
rp_sidt:
	movl %eax,(%edi)
	movl %edx,4(%edi)
	addl $8,%edi
	dec %ecx
	jne rp_sidt
!将idt的表基地址和段限长放入idtr表中
	lidt lidt_opcode
	ret

# -----------------------------------
!
write_char:
        !保存要用到的寄存器
	push %gs
	pushl %ebx
#	pushl %eax
        !让gs指向显示内存段
	mov $SCRN_SEL, %ebx
	mov %bx, %gs
        !字符显示位置值
	movl scr_loc, %ebx
        !因为还有一位属性值,故位置乘2
	shl $1, %ebx
        !显示字符
	movb %al, %gs:(%ebx)
        !恢复位置,然后再加一,如果等于2000则清0
	shr $1, %ebx
	incl %ebx
	cmpl $2000, %ebx
	jb 1f
	movl $0, %ebx
        !保存位置
1:	movl %ebx, scr_loc
        !恢复寄存器
	popl %ebx
	pop %gs
	ret

/***********************************************/
/* This is the default interrupt "handler" :-) */
.align 2
ignore_int:
	push %ds
	pushl %eax
	movl $0x10, %eax
	mov %ax, %ds
	movl $67, %eax            /* print 'C' */
	call write_char
	popl %eax
	pop %ds
	iret

/* Timer interrupt handler */
.align 2
timer_interrupt:
!保存寄存器,包括ax中的字符ASCII码,为了下次切换的时候返回,同时在tss中
!保存的是对应ljmp对应的下一个指令的地址
	push %ds
	pushl %eax
!指向内核段
	movl $0x10, %eax
	mov %ax, %ds
!向硬件写数据
	movb $0x20, %al
	outb %al, $0x20
	movl $1, %eax
!判断目前的任务号,然后判断跳转
	cmpl %eax, current
	je 1f
	movl %eax, current
	ljmp $TSS1_SEL, $0
	jmp 2f
!切换到0任务,然后切换tss,此时连堆栈也切换了,因此后面弹出的不是上面push
!的,而是前一次要切换到1任务是进入这个过程初始压入的ds和eax,同理切换到1任
!务
1:	movl $0, current
	ljmp $TSS0_SEL, $0
2:	popl %eax
	pop %ds
	iret

/* system call handler */
.align 2
system_interrupt:
!保存各个寄存器到堆栈
	push %ds
	pushl %edx
	pushl %ecx
	pushl %ebx
	pushl %eax
!数据段指向gdt 10项中的内核段
	movl $0x10, %edx
	mov %dx, %ds
!调用写字符过程
	call write_char
!恢复寄存器的值0
	popl %eax
	popl %ebx
	popl %ecx
	popl %edx
	pop %ds
	iret

/*********************************************/
current:.long 0
scr_loc:.long 0

.align 2
lidt_opcode:
	.word 256*8-1		# idt contains 256 entries
	.long idt		# This will be rewrite by code.
lgdt_opcode:
	.word (end_gdt-gdt)-1	# so does gdt
	.long gdt		# This will be rewrite by code.

	.align 8
idt:	.fill 256,8,0		# idt is uninitialized

gdt:	.quad 0x0000000000000000	/* NULL descriptor */
	.quad 0x00c09a00000007ff	/* 8Mb 0x08, base = 0x00000 */
	.quad 0x00c09200000007ff	/* 8Mb 0x10 */
	.quad 0x00c0920b80000002	/* screen 0x18 - for display */

	.word 0x0068, tss0, 0xe900, 0x0	# TSS0 descr 0x20
	.word 0x0040, ldt0, 0xe200, 0x0	# LDT0 descr 0x28
	.word 0x0068, tss1, 0xe900, 0x0	# TSS1 descr 0x30
	.word 0x0040, ldt1, 0xe200, 0x0	# LDT1 descr 0x38
end_gdt:
!这里一定要注意堆栈增长方向,栈底地址是0xbd8,用0初始化堆栈
	.fill 128,4,0
init_stack:                          # Will be used as user stack for task0.
	.long init_stack
	.word 0x10

/*************************************/
.align 8
!对应的段,段限长都是0x3ff,偏移地址都是0x0对应任务0
ldt0:	.quad 0x0000000000000000
	.quad 0x00c0fa00000003ff	# 代码段0x0f, base = 0x00000
	.quad 0x00c0f200000003ff	# 数据段0x17
!注意两个tss初始化不一样,第一次切到任务一是是从task1开始运行的,后面就不
!是了,其中task1处都改变了,这里的系统栈也用的init_stack
tss0:	.long 0 			/* back link */
	.long krn_stk0, 0x10		/* esp0, ss0 */
	.long 0, 0, 0, 0, 0		/* esp1, ss1, esp2, ss2, cr3 */
	.long 0, 0, 0, 0, 0		/* eip, eflags, eax, ecx, edx */
	.long 0, 0, 0, 0, 0		/* ebx esp, ebp, esi, edi */
	.long 0, 0, 0, 0, 0, 0 		/* es, cs, ss, ds, fs, gs */
	.long LDT0_SEL, 0x8000000	/* ldt, trace bitmap */

	.fill 128,4,0
krn_stk0:
#	.long 0

/************************************/
.align 8
!对应的段,段限长都是0x3ff,偏移地址都是0x0对应任务1
ldt1:	.quad 0x0000000000000000
	.quad 0x00c0fa00000003ff	# 0x0f, base = 0x00000
	.quad 0x00c0f200000003ff	# 0x17

tss1:	.long 0 			/* back link */
	.long krn_stk1, 0x10		/* esp0, ss0 */
	.long 0, 0, 0, 0, 0		/* esp1, ss1, esp2, ss2, cr3 */
	.long task1, 0x200		/* eip, eflags */
	.long 0, 0, 0, 0		/* eax, ecx, edx, ebx */
	.long usr_stk1, 0, 0, 0		/* esp, ebp, esi, edi */
	.long 0x17,0x0f,0x17,0x17,0x17,0x17 /* es, cs, ss, ds, fs, gs */
	.long LDT1_SEL, 0x8000000	/* ldt, trace bitmap */

	.fill 128,4,0
krn_stk1:

/************************************/
task0:
!这里我们去看一下ldt表中的17项,设置ds段
	movl $0x17, %eax
	movw %ax, %ds
!65对应A的ascii码
	movb $65, %al              /* print 'A' */
!调用80中断,这边我们再看设置80终端的代码
	int $0x80
!延迟作用
	movl $0xfff, %ecx
1:	loop 1b
!重复task0
	jmp task0

task1:
	movl $0x17, %eax
	movw %ax, %ds
	movb $66, %al              /* print 'B' */
	int $0x80
	movl $0xfff, %ecx
1:	loop 1b
	jmp task1

	.fill 128,4,0
usr_stk1:





        
Linux 0.00 intel 汇编语法,包含boot.s,head.s,以及编译添加汇编地址的对应文件 Linux 0.00 intel 汇编语法,包含boot.s,head.s,以及编译添加汇编地址的对应文件,可通过NASM进行编译, 立即下载

相关推荐

从TM1到TM9:手把手教你用Wireshark抓包分析LTE下行调度与传输模式切换

本文详细解析了如何使用Wireshark抓包分析LTE下行调度中的传输模式切换,从TM1到TM9的动态调整过程。通过实战案例,包括小区边缘移动、高速场景和多用户调度,揭示eNodeB如何基于信道质量指标(如RSRP、SINR)动态切换传输模式,并提供关键信令解析和优化建议,助力网络工程师提升LTE网络性能。

weixin_42651748的博客 316

Linux-0.11 boot目录head.s详解

Linux-0.11 boot目录head.s详解

小x的博客 3358

【电机学复习笔记】同步电机的特性及参数的求取

同步电机的主要特性包括:空载特性、短路特性、零功率因数负载特性、外特性和调整特性。 基于以上特性我们可以实现: 从空载特性和短路特性求同步电抗的不饱和值和短路比; 从零功率因数负载特性和空载特性确定保梯电抗(定子漏抗)和电枢反应电动势

Pantrick_的博客 2万+

linux 0.00,Linux0.00 “boot.s” 程序详解

/*程序描述:; boot.s程序编译出的代码共512字节,将被存放在软盘映像文件的第一个扇区中。PC在加电启动时,; BIOS程序会把启动盘上第一个扇区加载到物理内存0x7c00位置开始处,; 然后跳转到0x7c00处开始执行boot.s程序代码。; 本程序(boot.s程序)将内核代码(head.s代码)加载到0x10000处,然后再移动到0x0处0,; 注意;加载到0x0处是为了设置GDT表...

weixin_39614877的博客 387

头歌MySQL数据库实训答案 有目录

头歌java实训答案集数据库部分一条一条的写,可鼠标手动粘贴,除特定命令外未分大小写。 第1关:创建数据库 第2关创建表 第3关:使用主键约束 第4关:外键约束 第5关:添加常用约束 MySQL数据库 - 数据库和表的基本操作(一) 第1关:查看表结构与修改表名 第2关:修改字段名与字段数据类型 第3关:添加与删除字段 第4关:修改字段的排列位置 第5关:删除表的外键约束 MySQL数据库 - 数据库和表的基本操作(二) 第1关:插入数据 第2关:更新数据 第3关:删除数据 MySQL数据库 - 单表查询(

m0_67401761的博客 4万+

【软件逆向】带壳带反调试找flag教程(VMProtect3.0+X64dbg+ScyllaHide)

【软件逆向】带壳带反调试找flag教程(VMProtect 3.0+X64dbg+ScyllaHide)

zhangjiuding的博客 7516

Linux-0.01 引导代码分析-boot.s

Linux-0.01 的引导部分主要由两个源代码完成:boot.s 与 head.s 。boot.s 由 BIOS 加载执行,head.s 是 32 位的引导代码,在最后会调用 main() 函数,完成系统的引导。 boot.s 代码: ; ; boot.s ; ; boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself ; out of the way to address 0x90000, and j

Proteas的专栏 2780

ArcGISPro小白必看:5分钟搞定3D地形图制作(附免费数据源)

本文为ArcGISPro初学者提供5步制作专业3D地形图的完整指南,涵盖免费数据获取、项目初始化、数据预处理、3D场景构建和成果输出等关键步骤。特别推荐使用NASA的SRTM高程数据和吉林一号卫星影像,帮助用户快速掌握3D地形图制作技巧,适用于教学演示和科研分析。

weixin_28314575的博客 242

Linux0.00 “boot.s” 程序详解

;程序描述: ; boot.s程序编译出的代码共512字节,将被存放在软盘映像文件的第一个扇区中。PC在加电启动时, ; BIOS程序会把启动盘上第一个扇区加载到物理内存0x7c00位置开始处,然后跳转到0x7c00处开始执行boot.s程序代码。 ; 然后本程序将内核代码(head.s代码)加载到0x10000处,再移动到0x0处0,

wu55uw的专栏 2149

避坑指南:Windows下OpenCV摄像头索引混乱问题的3种解决之道

本文详细解析了Windows下OpenCV摄像头索引混乱问题的3种解决方案,包括GUID查询法、DirectShow接口集成和注册表固化技术。针对工业视觉和智能监控场景,提供实战代码和性能优化建议,帮助开发者稳定识别多路摄像头设备,有效解决VideoCapture接口的索引漂移问题。

weixin_30836759的博客 406

从零到一:KUKA机械臂与ROS的工业级通讯协议深度解析

本文深度解析KUKA机械臂与ROS的工业级通讯协议,重点对比EKI与RSI两种核心接口的技术特点与应用场景。详细介绍了网络架构设计、数据包解析机制及ROS-I集成方法,并提供实时性能优化与故障排除策略,为工程师实现高可靠性工业自动化集成提供完整解决方案。

2a4s6d8f0g的博客 296

kernel启动流程-head.S的执行_3.preserve_boot_args

1.前言 kernel版本:5.10 平台:arm64 本专题主要基于《arm64_linux head.S的执行流程》系列文章,前者是基于3.18,本专题针对的是内核5.10。主要分析head.S的执行过程。本文主要记录head.S的preserve_boot_args执行过程。 2.preserve_boot_args /*

HZero 1236

Qt版Dalsa线扫相机的采集Demo

Qt Dalsa

追赶时代的博客 605

移植u-boot到S3C2410

    最近计划将u-boot移植到我的S3C2410板子上,我的S3C2410板子上没有Norflash,只有64M的Nandflash,因此Bootloader是从Nandflash启动的,感觉和SMDK基本上差不多,所以vivi源码不需要任何修改,编译后就可以下载到板子上并启动,然后通过xmoden协议下载linux和root到内存中并烧写到Nandflash中,非常方便,但是美中不足的是v

Pamir的春天 4589

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

kernel 启动过程之一, uimge, zimage,arch/arm/boot/compressed/head.S

这几天因为工作原因,升级 2.6.22.7 的kernel 到 Mavell 的arm 板子上去,遇到一些头疼的问题,不得不分析启动代码, 郁闷阿。 zImage是ARM Linux常用的一种压缩映像文件,uImage是U-boot专用的映像文件,它是在zImage之前加上一个长度为0x40的“头”,说明这个映像文件的类型、加载位置、生成时间、大小等信息。换句话说,如果直接从uImag

pottichu的专栏 8328

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【Gemini-S1】【openvela】启动流程说明

硬件入口绑定:全志R528的汇编启动代码直接调用OpenVela内核的nx_start(),硬件启动完成即移交系统控制权;内核初始化绑定nx_start()通过架构专属接口(如)适配R528的硬件特性,为开发板提供核心运行基础;系统服务绑定创建的工作线程,专门处理开发板外设驱动,确保硬件功能正常响应;板级定制绑定作为OpenVela的板级入口,完成Gemini‑s1的专属硬件初始化;配置脚本绑定:通过动态脚本机制,无需修改内核即可适配开发板的个性化需求;交互层绑定。

RIVOTEK_OPENVELA的博客 787

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

AllWinner V3S BOOT0无uart log问题

AllWinner V3S BOOT0无uart log问题 分析与解决

LovelyPenguin的博客 257

HEAD请求实战指南:从原理到性能优化的深度探索

本文深入探讨了HEAD请求的原理与性能优化实践,详细解析了其在缓存验证、微服务健康检查、CDN预热等场景中的核心价值。通过实战案例与量化分析,展示了HEAD请求如何显著降低带宽消耗(最高达99.9%)并提升系统性能,是现代Web开发中不可或缺的HTTP工具。

weixin_34306593的博客 386

elasticsearch基础使用,以及spring boot调用es服务

本文介绍了Elasticsearch(ES)的安装配置、基础功能使用以及SpringBoot集成方法。主要内容包括:1)ES 7.12.1版本下载安装,配置可视化工具elasticsearch-head和Kibana;2)ES基础操作:健康度检查、索引查询、数据类型说明、分词功能详解;3)索引和文档的增删改查操作示例;4)SpringBoot集成ES的配置方法,包括创建索引、查询文档等API使用。文章提供了详细的步骤说明和代码示例,帮助开发者快速掌握ES的核心功能和应用场景。

weixin_74785181的博客 842

解压缩:arch/arm/boot/compressed/head.S分析

这几天因为工作原因,升级 2.6.22.7 的kernel 到 Mavell 的arm 板子上去,遇到一些头疼的问题, 不得不分析启动代码, 郁闷阿。   zImage是ARM Linux常用的一种压缩映像文件,uImage是U-boot专用的映像文件,它是在zImage之前加上一个长度为0x40的“头”,说明这个映像文件的类型、加载位置、生成时间、大小等信息。换句话说,如果直接从u

process的专栏 3174

Linux 0.00系统的编译运行与代码解析

简介 《Linux内核完全剖析》这本书在第4章4.9节给出了一个简单多任务内核示例程序,称之为Linux 0.00系统,给出实现这个简单内核的源程序:启动引导程序 boot.s 和保护模式多任务内核程序 head.s,实现了两个任务分别称为任务 A 和任务 B(或任务 0 和任务 1),它们会调用这个显示系统调用在屏幕上分别显示出字符’A’和’B’,直到每个 10 毫秒切换到另一个任务。任务 A ...

XBlog 1794

u-boot给内核传参说明

u-boot给内核传参说明machine_desc数据结构代码初始化小结   众所周知,u-boot传递给内核三个参数,即通过r0、r1、r2寄存器传递给内核。并且,r0的值暂时没有用到,缺省放0。   那么本篇文章主要来讲一下r1和r2的值 寄存器 含义 R1 机器号,标识计算机系统的型号 R2 ATAGS or dtb   说明:关于内核从head.S汇编执行到start_kernel部分这里就不介绍了。最终执行到start_kernel时。r1被赋值给__machine_arc

深海 1389

Linux 引导启动程序(boot)

主要描述 boot/目录中的三个汇编代码文件,见列表 3-1 所示。正如在前一章中提到的,这三个 文件虽然都是汇编程序,但却使用了两种语法格式。bootsect.s 和 setup.s 采用近似于 Intel 的汇编语言语法,需要使用 Intel  8086 汇编编译器和连接器 as86 和ld86,而 head.s 则使用 GNU 的汇编程序格式,并且运行在保护模式下,需要用 GNU 的 as

For free 697

U-Boot源码——lowlevel_init.S

U-Boot-2011.12 的board/samsung/smdk2410/lowlevel_init.S内容如下: #include #include /* some parameters for the board */ /* * * Taken from linux/arch/arm/boot/compressed/head-s3c2410.S * * Copyrigh

OneSea 1157

linux引导启动程序是什么意思,Linux 引导启动程序(boot)

主要描述 boot/目录中的三个汇编代码文件,见列表 3-1 所示。正如在前一章中提到的,这三个 文件虽然都是汇编程序,但却使用了两种语法格式。bootsect.s 和 setup.s 采用近似于 Intel 的汇编语言语法,需要使用 Intel 8086 汇编编译器和连接器 as86 和ld86,而 head.s 则使用 GNU 的汇编程序格式,并且运行在保护模式下,需要用 GNU 的 as ...

weixin_34688479的博客 483
上一篇: ubuntu ibus 无法全拼的问题
下一篇: 如何在ubuntu下安装jdk
jackyip2011
博客等级 码龄12年 5粉丝 17原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值