精华内容
下载资源
问答
  • #include <iostream> using namespace std; void main() { int a = 2; int *p = &a; cout<<p<<endl; } 0012FF7C 共计八位十六进制数字。 [img=...
  • 1 实模式在实模式下,处理器的内存寻址方式和8086处理器相同。2 计算机开机过程任何一台使用Intel 系列CPUPC机只要一开机,CPU就工作在实模式下。CPU从地址FFFF0H处开始执行指令,这是一条跳转指令,这条跳转指令...

    2015.03.25-26

    读《汇编语言》—王爽、《x86汇编语言:由实模式到保护模式》— 李忠、《30天自制操作系统》—川合秀实

    整理笔记。


    1 实模式

    在实模式下,处理器的内存寻址方式和8086处理器相同。


    2 计算机开机过程

    任何一台使用Intel 系列CPU的PC机只要一开机,CPU就工作在实模式下。CPU从地址FFFF0H处开始执行指令,这是一条跳转指令,这条跳转指令会跳到系统BIOS真正的启动代码处(进行硬件检测和初始化)。启动代码执行完毕后,调用int19h进行操作系统的引导,将计算机交由操作系统控制。


    如果你的机器装的是DOS,那么在DOS加载后CPU仍以实模式工作。如果你的机器装的是Windows,那么Windows加载后,将由Windows将CPU切换到保护模式下工作,因为Windows是多任务系统,它必须在保护模式下运行。Windows启动完成后,如果在Windows中运行一个DOS下的程序,那么Windows将CPU切换到虚拟8086下运行该程序。或者是这样,你点击开始菜单在程序项中进入MS-DOS方式,这时,Windows也将CPU切换到虚拟8086模式下运行。《汇编语言》第三版– 王爽。

    也就是说,将CPU由实模式到保护模式的切换是由操作系统完成的



    3 实模式下内存地址空间

    8086处理器有20根地址线,寻址范围为0x00000~ 0xFFFFF(1M)。

    Figure 1. 实模式下的内存地址空间

    实模式下的内存地址空间是各个存储器件的地址的逻辑组合,各个存储器中的存储单元的地址与内存地址空间中的地址一一对应。


    [1]处1KB内容是系统BIOS程序加载的(实际占用可能小于1KB);[2]处512字节内容是BIOS从磁盘/硬盘的第1柱面第1磁道的第1扇区读来的程序(此程序刚好512字节);[3]处128KB是显卡存储器的地址;[4]处256KB是存储BIOS程序的ROM存储器的地址。其中,最后64KB是存储系统BIOS程序的ROM存储器的地址,前192KB是其它存储BIOS程序的ROM存储器的地址。]


    在系统BIOS执行完毕后,可用的RAM地址空间为0x00400~ 0x07bff以及0x0800 ~ 0x9ffff。



    4 实模式下内存空间的访问

    8086处理器(CPU)内的寄存器都是16位的,地址线上的地址由CPU提供。CPU用两个16位的值合成一个20位的值:将一个16位的值乘以16(相当于这个16位的值保存在20位寄存器的低16位中,然后将低16位往高位移动了4位)再加上另一个16位的值。将这个由2个16位合成的值提供给20根地址线作为访问内存的地址值。被乘以16的那个值被称为段基址,没有被乘以16的那个值被称为偏移地址。


    CPU在实模式下,段寄存器中的值就是段基址,如果想要通过汇编程序访问某个内存单元,那么就需要指定一个段寄存器和一个偏移地址或以“段基址值:偏移地址值”的格式。CPU会将段寄存器的值乘以16再与偏移地址相加后,才将这个结果提供给地址线;用段基址和偏移地址的形式给出的表达式,CPU也会给段基址乘以16与偏移地址相加后,才将这个结果提供给地址线。

    Figure 2. 实模式下访问内存(得出内存地址)的方式

    这就是说,在汇编程序中,得用段基址:偏移地址的方式访问内存,因为CPU形成内存地址的方式是“段基址* 16 + 偏移地址”。

    按照“段:偏移地址”的方式访问内存是CPU对内存的一种管理方式。


    5 程序段和内存段的关系(程序的加载)

    实模式下的内存的段基址低4位都为0(段基址左移4位),段基址至少要是16的倍数。所以,内存中连续的两个段之间至少也会相差16字节,也就是说内存段之间以16字节对齐。


    汇编编译器将汇编程序中的“段名segment … 段名ends”伪指令对中的段名解释成一个程序段,程序加载器能够根据汇编编译器的解释将程序段加载到一个空闲的内存段中。

    如果汇编程序中未定义段,汇编编译器将所有的程序当成一个程序段,第一条语句作为程序的入口地址,程序加载器加载最终的可执行文件到内存中时,它首先找到能够容纳下整个程序的内存段,将程序加载到内存段中;如果汇编程序中有多个段,汇编编译器能识别程序入口地址所在的程序段,程序加载器加载这样的可执行文件时,首先去找到一块能够容纳下整个程序的内存空间,然后将包含程序入口地址的程序段加载到这段空闲内存空间第一个内存段中,然后将其余的段按照在程序中定义的顺序加载到这段空闲内存空间的后续内存段中,各个内存段以16字节对齐;如果汇编程序中有多个段,但没有包含程序入口地址的段,那么汇编编译器将程序中的第一个段作为程序入口地址,程序加载器按照各个段的定义顺序将它们载入内存中。(这是大多数加载器加载程序的方法,如果要写一个自己的加载器,不这么加载程序完全可以)


    1. assume cs:code, ds:data, ss:stack

    2. data segment

    3. dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedfh, 0cbah, 0987h

    4. data ends

    5. stack segment

    6. dw 0, 0, 0, 0, 0, 0, 0, 0

    7. stack ends

    8. code segment

    9. start:

    10. mov ax, stack

    11. mov ss, ax

    12. mov sp, 16

    13. mov ax, data

    14. mov ds, ax

    15. push ds:[0]

    16. push ds:[2]

    17. pop ds:[2]

    18. pop ds:[0]

    19. mov ax, 4c00h

    20. int 21h

    21. code ends

    22. end start           //告诉汇编编译器start标号处为程序的入口地址

    编译、连接此汇编程序,用debug调试器调试此程序,得到各个程序段对应的内存内存段:

    Figure 3. 程序段在内存中的内存段

    code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。(因为每个段的内容都未超过16字节)


    6 ORG

    ORG是由编译器处理的伪指令。它告知加载器,后续的程序应被加载至本内存段的哪个偏移地址处。它对段无效。

    assume cs:code
    code segment
    	jmp	my_label
    	;org 5h
    	my_label:
    		mov	ax, 0
    		
    		mov	ax,4c00h
    		int 21h
    code ends
    end


    将此段汇编程序编译、连接,用debug调试器观看生成的指令:

    Figure 4. 指令的参数为偏移地址

    将程序中的注释去掉,再将程序编译、连接,用debug观看生成的指令:

    Figure 5. org指定程序加载的偏移值

    程序加载器能够根据汇编编译器对org伪指令的处理信息而将org后面的指令装载到org指定的偏移地址处。同时修改某些指令的参数。


    7 磁盘启动区要求

    软盘的柱面:磁盘(软盘内存储数据的介质)的两面的相同位置的2磁道构成一个柱面。


    BIOS读软盘第一个扇区时,磁盘内不同地方的内容有不同的含义。以下是FAT12格式软盘第一扇区各内容的含义:

    表格 1. Windows (开机)读软盘第一个扇区的读法

    偏移

    长度/字节

    内容/含义

    (参考)值

    0

    3

    跳转到软盘指令开始处的跳转指令

    jmp l_start(l_start为软盘内第一条指令处的标号)

    3

    8

    第一个扇区的名字

    "xnlosipl"

    11

    2

    软盘每个扇区的大小(字节为单位)

    必须为512

    13

    1

    每簇的扇区数

    必须为1

    14

    2

    保留扇区数/FAT的起始位置/Boot记录占用扇区

    一般为1

    16

    1

    FAT的个数

    必须为2

    17

    2

    根目录文件数的最大值

    一般为224

    19

    2

    扇区总数

    (必须为)2880

    21

    1

    介质描述符

    必须为0xf0

    22

    2

    每FAT扇区数

    必须为9

    24

    2

    每磁道扇区数

    必须为18

    26

    2

    磁头数

    必须为2

    28

    4

    隐藏/不使用的扇区数

    必须为0

    32

    4

    如果偏移19处值为0,由这个值表示总扇区数

    2880

    36

    1

    中断13h的驱动器号

    固定为0

    37

    1

    未使用

    固定为0

    38

    1

    扩展引导标记

    固定为0x29

    39

    4

    卷列序号

    0xffffffff

    43

    11

    软盘名称

    "xnlhello-os"

    54

    8

    软盘格式名称

    "FAT12   "(8字节,空格填充)

    62

    448

    (引导)代码、数据及其它填充字符

    ……

    510

    2

    标明软盘有无所需的启动代码(在第一个扇区内)

    0x55aa(为0x55aa表明有)

    这些规定都是指电平信号(在二进制编辑器中可直接书写就可得到它们)。在软盘内每个偏移内组织的数据要符合“表格 1”中的要求。这样,软盘内的数据才会得到计算机的正确解释


    启动区外,除下图有2个地方有规定(非必须)内容外,其它地方的内容无规定。



    [x86OS] Note Over.



    展开全文
  • 内存分配代码格式

    2019-02-19 13:04:49
    关于内存分配一些代码格式 1.内存起名(把内存的实际地址分区间取名) memery{ VECS : o = 0x10800000 l = 0x00000200 BOOT : o = 0x10800200 l = 0x00000200 IRAM : o = 0x10800400 l = 0x0001FA00 DDR2 : o ...

    关于内存分配的一些代码格式

    1.内存起名(把内存的实际地址分区间取名)

    memery{
    
    VECS : o = 0x10800000   l = 0x00000200
    BOOT : o = 0x10800200   l = 0x00000200
    IRAM : o = 0x10800400   l = 0x0001FA00
    DDR2 : o = 0x80000000   l = 0x10000000
    
    }
    

    2.起段名,并对应内存名

    section{
    
    .bss   > IRAM
    .cinit > IRAM
    .cio   > IRAM
    .const > DDR2
    .data  > IRAM
    .far   > IRAM
    .stack > IRAM
    .system > IRAM
    .text  > IRAM
    .ddr2  > DDR2
    
    }
    

    这里的段名.bss ~ .ddr2
    有的是编译器直接起好了名字,有的是自己起的名字,
    .ddr2这个段就是自己起的名字。段是用来存放某种类型的数据的,
    我们把有特定含义或者相同点的数据放到自己想要的段里面,方便管理,
    .bss、.text等都是C编译器编译之后自己生产的段
    段只是在名义上说明了或者规定了变量存在哪,但是还没有说明具体存放在哪个内存区域
    只有.bss > IRAM语句执行了,才能将 变量 段 内存地址联系在一起,这句话的意思是
    段.bss对应到内存的IRAM块,同时我们(或者编译器)规定哪些变量存放在什么段内,这就将变量直接对应到内存上了

    3.将变量规定到特定的段内(我们想自己规定,不按照编译器的默认规定,如果自己不规定,编译器会自己默认有一套数据存放到段的分配方式)

    在变量定义的文件中:

    #pragma  data_section(name_var, ".far");     //将名字为name_var的变量定义到了“.far”这个段中;
    #pragma  data_align(name_var,   .......);			//这个可以设置数据的一些存放读取格式;
    float name_var[100];					//定义了一个float类型的数组在“.far”段中
    
    展开全文
  • 在实模式下,处理器的内存寻址方式和8086处理器相同。 2 计算机开机过程 任何一台使用Intel 系列CPUPC机只要一开机,CPU就工作在实模式下。CPU从地址FFFF0H处开始执行指令,这是一条跳转指

    2015.03.25-26

    读《汇编语言》—王爽、《x86汇编语言:由实模式到保护模式》— 李忠、《30天自制操作系统》—川合秀实

    整理笔记。


    1 实模式

    在实模式下,处理器的内存寻址方式和8086处理器相同。


    2 计算机开机过程

    任何一台使用Intel 系列CPU的PC机只要一开机,CPU就工作在实模式下。CPU从地址FFFF0H处开始执行指令,这是一条跳转指令,这条跳转指令会跳到系统BIOS真正的启动代码处(进行硬件检测和初始化)。启动代码执行完毕后,调用int19h进行操作系统的引导,将计算机交由操作系统控制。


    如果你的机器装的是DOS,那么在DOS加载后CPU仍以实模式工作。如果你的机器装的是Windows,那么Windows加载后,将由Windows将CPU切换到保护模式下工作,因为Windows是多任务系统,它必须在保护模式下运行。Windows启动完成后,如果在Windows中运行一个DOS下的程序,那么Windows将CPU切换到虚拟8086下运行该程序。或者是这样,你点击开始菜单在程序项中进入MS-DOS方式,这时,Windows也将CPU切换到虚拟8086模式下运行。《汇编语言》第三版– 王爽。

    也就是说,将CPU由实模式到保护模式的切换是由操作系统完成的


    3 实模式下内存地址空间

    8086处理器有20根地址线,寻址范围为0x00000~ 0xFFFFF(1M)。

    Figure 1. 实模式下的内存地址空间

    实模式下的内存地址空间是各个存储器件的地址的逻辑组合,各个存储器中的存储单元的地址与内存地址空间中的地址一一对应。


    [1]处1KB内容是系统BIOS程序加载的(实际占用可能小于1KB);[2]处512字节内容是BIOS从磁盘/硬盘的第1柱面第1磁道的第1扇区读来的程序(此程序刚好512字节);[3]处128KB是显卡存储器的地址;[4]处256KB是存储BIOS程序的ROM存储器的地址。其中,最后64KB是存储系统BIOS程序的ROM存储器的地址,前192KB是其它存储BIOS程序的ROM存储器的地址。]


    在系统BIOS执行完毕后,可用的RAM地址空间为0x00400~ 0x07bff以及0x0800 ~ 0x9ffff。


    4 实模式下内存空间的访问

    8086处理器(CPU)内的寄存器都是16位的,地址线上的地址由CPU提供。CPU用两个16位的值合成一个20位的值:将一个16位的值乘以16(相当于这个16位的值保存在20位寄存器的低16位中,然后将低16位往高位移动了4位)再加上另一个16位的值。将这个由2个16位合成的值提供给20根地址线作为访问内存的地址值。被乘以16的那个值被称为段基址,没有被乘以16的那个值被称为偏移地址。


    CPU在实模式下,段寄存器中的值就是段基址,如果想要通过汇编程序访问某个内存单元,那么就需要指定一个段寄存器和一个偏移地址或以“段基址值:偏移地址值”的格式。CPU会将段寄存器的值乘以16再与偏移地址相加后,才将这个结果提供给地址线;用段基址和偏移地址的形式给出的表达式,CPU也会给段基址乘以16与偏移地址相加后,才将这个结果提供给地址线。

    Figure 2. 实模式下访问内存(得出内存地址)的方式


    这就是说,在汇编程序中,得用段基址:偏移地址的方式访问内存,因为CPU形成内存地址的方式是“段基址* 16 + 偏移地址”。

    按照“段:偏移地址”的方式访问内存是CPU对内存的一种管理方式。


    5 程序段和内存段的关系(程序的加载)

    实模式下的内存的段基址低4位都为0(段基址左移4位),段基址至少要是16的倍数。所以,内存中连续的两个段之间至少也会相差16字节,也就是说内存段之间以16字节对齐。


    汇编编译器将汇编程序中的“段名segment … 段名ends”伪指令对中的段名解释成一个程序段,程序加载器能够根据汇编编译器的解释将程序段加载到一个空闲的内存段中。


    如果汇编程序中未定义段,汇编编译器将所有的程序当成一个程序段,第一条语句作为程序的入口地址,程序加载器加载最终的可执行文件到内存中时,它首先找到能够容纳下整个程序的内存段,将程序加载到内存段中;如果汇编程序中有多个段,汇编编译器能识别程序入口地址所在的程序段,程序加载器加载这样的可执行文件时,首先去找到一块能够容纳下整个程序的内存空间,然后将包含程序入口地址的程序段加载到这段空闲内存空间第一个内存段中,然后将其余的段按照在程序中定义的顺序加载到这段空闲内存空间的后续内存段中,各个内存段以16字节对齐;如果汇编程序中有多个段,但没有包含程序入口地址的段,那么汇编编译器将程序中的第一个段作为程序入口地址,程序加载器按照各个段的定义顺序将它们载入内存中。(这是大多数加载器加载程序的方法,如果要写一个自己的加载器,不这么加载程序完全可以)
    assume	cs:code, ds:data, ss:stack
    
    data	segment
    	dw	0123h, 0456h, 0789h, 0abch, 0defh, 0fedfh, 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, 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           //告诉汇编编译器start标号处为程序的入口地址
    

    编译、连接此汇编程序,用debug调试器调试此程序,得到各个程序段对应的内存内存段:

    Figure 3. 程序段在内存中的内存段

    code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。(因为每个段的内容都未超过16字节)


    6 ORG

    ORG是由编译器处理的伪指令。它告知加载器,后续的程序应被加载至本内存段的哪个偏移地址处。它对段无效。

    assume cs:code
    
    code segment
    	jmp	my_label
    
    	;org 5h
    
    	my_label:
    		mov	ax, 0
    		
    		mov	ax,4c00h
    		int 21h
    code ends
    end
    

    将此段汇编程序编译、连接,用debug调试器观看生成的指令:

    Figure 4. 指令的参数为偏移地址

    将程序中的注释去掉,再将程序编译、连接,用debug观看生成的指令:

    Figure 5. org指定程序加载的偏移值

    程序加载器能够根据汇编编译器对org伪指令的处理信息而将org后面的指令装载到org指定的偏移地址处。同时修改某些指令的参数。


    7 磁盘启动区要求

    软盘的柱面:磁盘(软盘内存储数据的介质)的两面的相同位置的2磁道构成一个柱面。

    BIOS读软盘第一个扇区时,磁盘内不同地方的内容有不同的含义。以下是FAT12格式软盘第一扇区各内容的含义:

    表格 1. Windows (开机)读软盘第一个扇区的读法

    偏移

    长度/字节

    内容/含义

    (参考)值

    0

    3

    跳转到软盘指令开始处的跳转指令

    jmp l_start(l_start为软盘内第一条指令处的标号)

    3

    8

    第一个扇区的名字

    "xnlosipl"

    11

    2

    软盘每个扇区的大小(字节为单位)

    必须为512

    13

    1

    每簇的扇区数

    必须为1

    14

    2

    保留扇区数/FAT的起始位置/Boot记录占用扇区

    一般为1

    16

    1

    FAT的个数

    必须为2

    17

    2

    根目录文件数的最大值

    一般为224

    19

    2

    扇区总数

    (必须为)2880

    21

    1

    介质描述符

    必须为0xf0

    22

    2

    每FAT扇区数

    必须为9

    24

    2

    每磁道扇区数

    必须为18

    26

    2

    磁头数

    必须为2

    28

    4

    隐藏/不使用的扇区数

    必须为0

    32

    4

    如果偏移19处值为0,由这个值表示总扇区数

    2880

    36

    1

    中断13h的驱动器号

    固定为0

    37

    1

    未使用

    固定为0

    38

    1

    扩展引导标记

    固定为0x29

    39

    4

    卷列序号

    0xffffffff

    43

    11

    软盘名称

    "xnlhello-os"

    54

    8

    软盘格式名称

    "FAT12   "(8字节,空格填充)

    62

    448

    (引导)代码、数据及其它填充字符

    ……

    510

    2

    标明软盘有无所需的启动代码(在第一个扇区内)

    0x55aa(为0x55aa表明有)

    这些规定都是指电平信号(在二进制编辑器中可直接书写就可得到它们)。在软盘内每个偏移内组织的数据要符合“表格 1”中的要求。这样,软盘内的数据才会得到计算机的正确解释


    启动区外,除下图有2个地方有规定(非必须)内容外,其它地方的内容无规定。



    [x86OS] Note Over.

    [2015.04.01]

    展开全文
  • 因为书里的一些题目很多时候需要查看变量的【位级表示 / 字节表示 / 内存地址】,然而对简单打印出来的格式很不满意,所以想着 Qt 中比较好用的 QTextStream 来进行格式化输出 ( QDebug 也可以,但还不够方便)。...

    【写在前面】

    最近在看《深入理解计算机系统 第二版》简称 CSAPP,这本书我是极力推荐的,深度和广度都有 ( 而且讲解得非常仔细 )。

    然后自己是第二遍看了 ( 之前看的第一版,第二版有不少新东西 ),里面的题也是一直跟着做的,就顺手写了几个小函数来方便做题。

    因为书里的一些题目很多时候需要查看变量的 【位级表示 / 字节表示 / 内存地址】,然而对简单打印出来的格式很不满意,所以想着 Qt 中比较好用的 QTextStream 来进行格式化输出 ( QDebug 也可以,但还不够方便)。

    所以这里就简单分享一些小技巧吧。


    【正文开始】 

    先来看代码:

    #include <QCoreApplication>
    #include <QDebug>
    
    void show_addr(void *in, size_t size)
    {
        QString result;
        QTextStream stream(&result);
        stream.setFieldWidth(12);
        stream.setFieldAlignment(QTextStream::AlignLeft);
        stream << "address: ";
        stream.setFieldAlignment(QTextStream::AlignRight);
        for (size_t i = 0; i < size; i++) {
            stream << static_cast<uchar *>(in) + i;
        }
    
        qDebug().noquote() << result;
    }
    
    void show_bits(void *in, size_t size)
    {
        QString result;
        QTextStream stream(&result);
        stream.setFieldWidth(12);
        stream.setFieldAlignment(QTextStream::AlignLeft);
        stream << "bits: ";
        stream.setFieldAlignment(QTextStream::AlignRight);
        for (size_t i = 0; i < size; i++) {
            uchar uc = static_cast<uchar *>(in)[i];
            stream << QString::number(uc, 2).rightJustified(8, '0');
        }
    
        qDebug().noquote() << result;
    }
    
    void show_bytes(void *in, size_t size)
    {
        QString result;
        QTextStream stream(&result);
        stream.setFieldWidth(12);
        stream.setFieldAlignment(QTextStream::AlignLeft);
        stream << "bytes: ";
        stream.setFieldAlignment(QTextStream::AlignRight);
        for (size_t i = 0; i < size; i++) {
            uchar uc = static_cast<uchar *>(in)[i];
            stream << QString::number(uc, 16).rightJustified(2, '0');
        }
    
        qDebug().noquote() << result;
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        uint64_t mx = static_cast<uint64_t>(-1);
        show_bits(&mx, sizeof(mx));
        show_bytes(&mx, sizeof(mx));
        show_addr(&mx, sizeof(mx));
    
        return a.exec();
    }
    

    输出如下 ( 注意: 我的电脑是小端字节序 ):

    可以看到,格式化后的输出顺眼多了 。

    其中,主要依靠这几个函数完成:

    QString QString::number(long n, int base = 10):

    将数数字(整数、浮点数、有符号、无符号等)转换为 QString 类型,而基数可以简单的理解为进制。

    QString QString::rightJustified(int width, QChar fill = QLatin1Char(' '), bool truncate = false) const:

    返回一个 size() 宽度的字符串,其中包含填充字符,后跟该字符串。 例如:

    QString s =“apple”;

    QString t = s.rightJustified(8,'.'); // t ==“ ...apple”

    如果 truncate false 并且字符串的 size() 大于 width,则返回的字符串是该字符串的副本。

    如果 truncate true,并且字符串的 size() 大于 width,则结果字符串在位置 width 处被截断。

    QString str = “Pineapple”;

    str = str.rightJustified(5,'.',true); // str ==“Pinea”

    void QTextStream::setFieldWidth(int width):

    将当前字段的宽度设置为 width 。 如果 width 为 0 ( 默认值 ),则字段宽度等于生成的文本的长度。

    注意:字段宽度适用于调用此函数后附加到此流的每个元素 ( 例如,它也填充 endl )。 此行为不同于 STL 中的类似类,在 STL 中,字段宽度仅适用于下一个元素。

    QTextStream :: setFieldAlignment(QTextStream :: FieldAlignment mode):

    将字段对齐方式设置为 mode。 与 setFieldWidth() 一起使用时,此函数允许您生成格式化的输出,其中文本左对齐右对齐居中对齐。  

    void QTextStream::setPadChar(QChar ch) :

     将填充字符设置为 ch。 默认值为 ASCII 空格字符 (' ') 或 QChar(0x20)。 生成文本时,此字符用于填充字段中的空格,即超过 fieldWidth() 的部分。


    【结语】

    实际上,另一种方法是使用 QTextStream bin() / hex() / setIntegerBase() 也能达到同样的效果,但是会麻烦许多。

    最后再推荐一次《深入理解计算机系统 第二版》,话说第二版题目的答案都详细很多了,很赞 👍。

    展开全文
  • #includeint main() {/*______...// /打印a的内存地址,使用&取出内存地址,0x7fff59c9cc78printf("a地址:%p\n",&a);/*_______________数组定义_________________*///基本格式: 数据类型 书组名[存放...
  • big endian 和 small endian 在intel机器上都是采用small endian即小端字节序,也就是地位的地址低,高位的地址高。 int i = 0x12345678 char c1 = *(char*)(&i) 一个int型整数的地址就是其最低位的地址,...
  • 2.3 高速缓冲存储器(Cache) 2.3.1 高速缓冲存储器的功能、结构与工作原理 高速缓冲存储器是存在于主存与CPU之间的一级存储器, 由静态存储...为此需要解决2个技术问题:一是主存地址与缓存地址的映象及转换; 二是按
  • gdb查看内存地址里面数据

    千次阅读 2015-06-23 16:37:40
    gdb查看指定地址的内存地址的值:examine 简写 x-----使用gdb> help x 来查看使用方式 x/ (n,f,u为可选参数)n: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u...
  • gdb查看指定地址的内存地址的值:examine 简写 x-----使用gdb> help x 来查看使用方式 x/ (n,f,u为可选参数) n: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面...
  • 什么是内存对齐?理论上计算机对于任何变量访问都可以从任意位置开始,然而实际上系统会对这些变量存放地址有限制,通常将变量首地址设为某个数N倍数,这就是内存对齐。为什么要内存对齐?1....
  • 得到元素的内存地址

    2013-07-30 23:06:13
    //得到元素的内存地址 #include #include int main() { int x[6]={1,2,3,4,5,6}; int i; for(i=0;i;i++) { printf("&x[%d]值是:%p",i,&x[i]);//%p格式控制符 printf("\n"); } for(i=0;i;i++) {...
  • n : 表示要显示的内存单元个数f : 表示显示方式, 可取如下值 x 按十六进制格式显示变量。 d 按十进制格式显示变量。 u 按十进制格式显示无符号整型。 o 按八进制格式显示变量。 t 按二进制格式显示变量。 a 按十六...
  • 大端格式、小端格式,以及数据在内存存储方式 内存的地址.左→右,地址降低,下→上,地址升高。一个格子是一个字节,一个字节是8位。 int a = 0x01020304 若为小端格式(arm默认是小段格式)  内存格式 ...
  • si和di是专门用于表示偏移地址的寄存器,与[bx+idata]类似 还可以使用[bx+si]或[bx+di],表示偏移地址为bx中的值加si/di中的值 常用[bx][si/di]的格式表示 也可以使用[bx+idata+si/di] 常用idata[bx]
  • Shell- ipv6地址的格式转化

    千次阅读 2018-11-06 09:50:42
    分析:ip a与ifconfig显示的结果中没有网卡和ipv6地址的对应关系,所以想到去内存中匹配,但是内存中的ipv6地址与ip a看到的地址格式不同,因此需要做转化。即将2003:a:12:bcd:a3b4::200转化成2003000a00120bcda3b...
  • 内存映射(IO地址和内存地址

    千次阅读 2012-07-16 00:04:12
    ARM体系结构下面内存和i/o映射区别 (1)关于IO与内存空间: 在X86处理器中存在着I/O空间概念,I/O空间是相对于内存空间而言,它通过...端口号标识了外设寄存器地址。Intel语法in、out指令格式为: IN 累
  • 用于学习如何计算计算机内存地址的交互式工具。 专门用于研究在给定教科书问题的特定输入的情况下如何形成直接映射的高速缓存存储器地址。 学分 作者:梅根·奥尼尔(Megan O'Neill) 最初的时间: 2018年3月27日-...
  • 原文地址:http://blog.csdn.net/biblereader/archive/2006/06/21/819428.aspx   我两年前就知道不应该用==号来判断浮点数相等了,因为存在一个精度问题,但是一直以来,都没怎么在乎这些东西,而实际上,我...
  • C++:cup内存存储格式

    2020-07-07 15:47:54
    大端存储就是变量十六进制中高位地址保存到CPU内存的地位地址中。 小端存储就是变量十六进制中地位地址保存到CPU内存的地位地址中 2、计算数组指针的内存大小sizeof() 注意:指针的内存大小与系统有关,32位都是4...
  • 因为输出格式“%d”原因?这是由于 printf("%d",&amp;a);输出地址为有符号10进制,printf("%p“,&amp;a);输出地址为16进制;d代表整数格式,输出为有符号10进制;p代表是指针格式,...
  •  gdb查看指定地址的内存地址的值:examine 简写 x-----使用gdb> help x 来查看使用方式  x/ (n,f,u为可选参数) n: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由...
  • 转移地址内存jmp指令有两种格式: (1)jmp word ptr 内存单元地址(段内转移) 功能:从内存单元地址处开始存放着一个字,是转移目的偏移地址。 mov ax,0123h mov ds:[0],ax jmp word ptr ds:[0] 执行之后...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,946
精华内容 1,578
关键字:

内存地址的格式