当前位置: 首页 > news >正文

wordpress la国外seo工具

wordpress la,国外seo工具,wordpress 千万级数据,怎么查看网站开发人使用C语言生成一个二进制文件 使用自己喜欢的文本编辑器写一个test.c#xff1a; int main() { } 再使用如下命令编译#xff1a; gcc –c test.c ld –o test –Ttext 0x0 –e main test.o objcopy –R .note –R .comment –S –O binary test test.bin 最后生成的二进…使用C语言生成一个二进制文件 使用自己喜欢的文本编辑器写一个test.c int main() { } 再使用如下命令编译 gcc –c test.c ld –o test –Ttext 0x0 –e main test.o objcopy –R .note –R .comment –S –O binary test test.bin 最后生成的二进制文件是test.bin可以使用你喜欢的反汇编工具看看这个文件里到底是什么。我使用Linux下的objdump进行反汇编 objdump –D –b binary –a i386 test.bin 结果如下 00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c9                        leave    11:          c3                        ret   其中第一列是指令的内存地址第二列是指令的机器码第三列是汇编指令。相信你的结果与此同。如果你的gcc与我的不一样例如2.7.x版本的gcc你的结果很可能会有所不同缺少如下的四条指令这是正常的这两个版本的gcc所使用的堆栈框架不同下面介绍的例子也会因为编译器版本的不同造成其结果有别 3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp #堆栈对齐以16Bytes为单位分配局部变量空间    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp 上述代码都是32-bit代码你需要在像Linux这样的 32-bit环境下运行并且是保护模式。也可以只用下面的指令直接生成test.bin gcc –c test.c ld –Ttext 0x0 –e main --oformat binary –o test.bin test.o 上面的test.c中只有一个函数而且还只是个框架。其反汇编代码也没什么难理解的。 3.         编写带局部变量的程序 再创建一个新的test.c看看gcc是如何处理局部变量的。 int main() { int i; i0x12345678; } 使用上述两种方法的人一种编译生成test.bin。然后使用objdump进行反汇编 00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c7 45 fc 78 56 34 12    movl   $0x12345678,0xfffffffc(%ebp)   17:          c9                        leave    18:          c3                        ret 与第一个例子相比开头的六条指令和最后的两条指令完全相同仅有一条指令不同。这条语句是给局部变量赋值其空间的分配在前面已经进行了。在gcc中堆栈中的局部变量空间按16字节为单位进行分配而不是通常的1字节为单位。如果将 int i; i0x12345678; 改为 int i0x12345678; 其结果没有区别。但是如果是全局变量就不一样了。 4.         编写带全局变量的程序 将test.c改为 int i; int main() { i0x12345678; } 使用同样的方法编译然后再进行反汇编 00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c7 05 1c 10 00 00 78   movl   $0x12345678,0x101c   17:          56 34 12   1a: c9                        leave    1b:          c3                        ret    我们定义的全局变量被放到了0x101c处这是gcc默认以page-align对齐数据段的结果此处的page与页式内存管理中的page没有关系。在使用ld链接时使用-N参数可以关闭对齐效果。 00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c7 05 1c 00 00 00 78   movl   $0x12345678,0x1c   17:          56 34 12   1a: c9                        leave    1b:          c3                        ret  正如我们看到的数据段紧接着代码段。我们也可以明确的指定数据段的位置试试下面的命令再进行编译 gcc –c test.c ld –Ttext 0x0 –Tdata 0x1234 –e main –N --oformat binary –o test.bin test.o 然后再使用objdump进行反汇编 00000000 .data:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c7 05 34 12 00 00 78   movl   $0x12345678,0x1234   17:          56 34 12   1a: c9                        leave    1b:          c3                        ret    现在我们定义的全局变量被放到0x1234处了。通过给ld指定-Tdata参数可以自由的定义数据段的地址如果不指定数据段在代码段后。 再看看直接给全局变量进行初始化的情况。 const int I0x12345678; int main() { } 仍然使用上面的方法进行编译、链接、反汇编其结果如下 00000000 .data:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c9                        leave    11:          c3                        ret      12:          00 00                      add    %al,(%eax)   14:          78 56                      js     0x6c   16:          34 12                      xor    $0x12,%al 代码以4Bytes对齐全局变量被直接存储在代码段之后的数据段ld直接将常数放到了全局变量的位置一步到位。 使用如下命令可以看到更多细节 objdump –D test.o 可以看到如下的结果 test.o:     file format elf32-i386   Disassembly of section .text:   00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c9                        leave    11:          c3                        ret    Disassembly of section .data: Disassembly of section .rodata:   00000000 i:    0:          78 56                      js     58 main0x58    2:          34 12                      xor    $0x12,%al 我们可以更清楚地看到在.c文件中定义的全局常量被放在了只读的数据段中了。再看下面的一段代码 int I0x12345678; const int c0x12345678; int main() { } 还是使用上面的方法编译、链接、反汇编可以到到如下结果 test.o:     file format elf32-i386   Disassembly of section .text:   00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c9                        leave    11:          c3                        ret    Disassembly of section .data:   00000000 i:    0:          78 56                      js     58 main0x58    2:          34 12                      xor    $0x12,%al Disassembly of section .rodata:   00000000 c:    0:          78 56                      js     58 main0x58    2:          34 12                      xor    $0x12,%al 可以看出整数I被放在了普通的数据段中常数c被放在了只读数据段中了。当使用全局变量常量时ld会自动的使用合适的数据段存储他们。 5.         处理指针 使用如下代码来查看gcc处理指针变量的情况 int main() { int I; int* p; pI; *p0x12345678; } 使用objdump查看生成的机器代码 00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:         8d 45 fc                     lea    0xfffffffc(%ebp),%eax   13:         89 45 f8                    mov    %eax,0xfffffff8(%ebp)   16:         8b 45 f8                    mov    0xfffffff8(%ebp),%eax   19:         c7 00 78 56 34 12    movl   $0x12345678,(%eax)   1f: c9                        leave    20:          c3                        ret    一开始gcc已经为局部变量预分配了至少8Bytes的空间并且使esp以16Bytes边界对齐如果还需要额外的空间gcc将按照16Bytes为单位进行分配而不是其他编译器所使用的以1Byte为单位进行分配。变量I位于ebp-4变量p位于ebp-8lea指令将I的有效地址放入eax中然后又被放入p中。最后将0x12345678赋给p指向的变量I。 6.         关于函数调用 看如下代码 void func(); int main() { func(); } void func() { } 再看生成的二进制代码 00000000 .data:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          e8 03 00 00 00                call   0x18   15:          c9                        leave    16:          c3                        ret      17:          90                        nop      18:          55                        push   %ebp   19:          89 e5                      mov    %esp,%ebp   1b:          c9                        leave    1c: c3                        ret    主函数main通过call指令调用了空函数func该函数与main大同小异。为ld指定-Map开关输出map文件可以得到更详细的信息。 .text           0x00000000       0x1d  *(.text .stub .text.* .gnu.linkonce.t.*)  .text          0x00000000       0x1d       test.o                 0x00000000                main                 0x00000018                func 第一列是段名这里是.text第二列是起始位置第三列是段长度最后一列是附加信息如函数名、所出自的目标文件等。可以看到.text段从0x0开始长度为0x1d函数func从0x18开始。 7.         函数的返回值 看下面的代码主函数main返回一个整型值 int main() { return 0x12345678; } 所生成的二进制代码与其他编译器大同小异 00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          b8 78 56 34 12                mov    $0x12345678,%eax   15:          c9                        leave    16:          c3                        ret    你已经看到了gcc使用eax传递返回值。因为返回值就是eax寄存器的值所以你可以隐含的返回甚至什么都不返回。因为返回值保存在寄存器中进行函数调用时经常忽略返回值。例如我们经常这样调用函数 printf(…); 该函数是有返回值的。如果函数返回的数据大于4Bytes就不能再使用这种方法返回数据了。再看下面的例子 typedef strUCt mydef{ int a,b,c,d; int array[10]; }mydef;   mydef func(); int main() { mydef d; dfunc(); } mydef func() { mydef d; return d; } 接着看反汇编的代码 00000000 .data:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 48                    sub    $0x48,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          8d 45 b8                    lea    0xffffffb8(%ebp),%eax   13:          83 ec 0c                     sub    $0xc,%esp   16:          50                        push   %eax   17:          e8 06 00 00 00                call   0x22   1c: 83 c4 0c                    add    $0xc,%esp   1f: c9                        leave    20:          c3                        ret      21:          90                        nop      22:          55                        push   %ebp   23:          89 e5                      mov    %esp,%ebp   25:          57                        push   %edi   26:          56                        push   %esi   27:          83 ec 40                    sub    $0x40,%esp   2a: 8b 7d 08                    mov    0x8(%ebp),%edi   2d:          8d 75 b8                    lea    0xffffffb8(%ebp),%esi   30:          fc                         cld      31:          b8 0e 00 00 00                mov    $0xe,%eax   36:          89 c1                      mov    %eax,%ecx   38:          f3 a5                       repz movsl %ds:(%esi),%es:(%edi)   3a: 8b 45 08                    mov    0x8(%ebp),%eax   3d:          83 c4 40                    add    $0x40,%esp   40:          5e                        pop    %esi   41:          5f                        pop    %edi   42:          c9                        leave    43:          c2 04 00                    ret    $0x4 我们自定义的结构为0x38Bytesgcc为了保持堆栈的16Bytes对齐分配了0x40Bytes的空间。函数func并没有参数但是在调用时却将变量d的指针传了进去。然后利用这个指针使用指令movsl直接对d进行赋值。再看下面的例子 typedef struct mydef{ int a,b,c,d; int array[10]; }mydef;   mydef func(); int main() { func(); } mydef func() { mydef d; return d; } 再看反汇编的结果 00000000 .data:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 48                    sub    $0x48,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          8d 45 b8                    lea    0xffffffb8(%ebp),%eax   13:          83 ec 0c                     sub    $0xc,%esp   16:          50                        push   %eax   17:          e8 06 00 00 00                call   0x22   1c: 83 c4 0c                    add    $0xc,%esp   1f: c9                        leave    20:          c3                        ret      21:          90                        nop      22:          55                        push   %ebp   23:          89 e5                      mov    %esp,%ebp   25:          57                        push   %edi   26:          56                        push   %esi   27:          83 ec 40                    sub    $0x40,%esp   2a: 8b 7d 08                    mov    0x8(%ebp),%edi   2d:          8d 75 b8                    lea    0xffffffb8(%ebp),%esi   30:          fc                         cld      31:          b8 0e 00 00 00                mov    $0xe,%eax   36:          89 c1                      mov    %eax,%ecx   38:          f3 a5                       repz movsl %ds:(%esi),%es:(%edi)   3a: 8b 45 08                    mov    0x8(%ebp),%eax   3d:          83 c4 40                    add    $0x40,%esp   40:          5e                        pop    %esi   41:          5f                        pop    %edi   42:          c9                        leave    43:          c2 04 00                    ret    $0x4 可以说与上面的结果一字不差我们没有在main函数中声明变量存储func返回的结果但是gcc替我们做了。它仍然为函数func传递了一个指针并将结果传了出来尽管我们对返回值不感兴趣但编译器对我们的兴趣好像也没有兴趣依然我行我素。如果使用了优化选项结果很可能有所相同。 8.         给函数传递参数 gcc遵循一般的c语言标准包括参数传递方式。看看下面的例子 char res; char func(char a,char b); int main() { resfunc(0x02,0x03); } char func(char a,char b) { return ab; } 再看看他的反汇编代码 00000000 .data:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          83 ec 08                    sub    $0x8,%esp   13:          6a 03                      push   $0x3   15:          6a 02                      push   $0x2   17:          e8 0a 00 00 00                call   0x26   1c: 83 c4 10                    add    $0x10,%esp   1f: a2 44 00 00 00                mov    %al,0x44   24:          c9                        leave    25:          c3                        ret      26:          55                        push   %ebp   27:          89 e5                      mov    %esp,%ebp   29:          83 ec 04                    sub    $0x4,%esp   2c: 8b 45 08                    mov    0x8(%ebp),%eax   2f: 8b 55 0c                    mov    0xc(%ebp),%edx   32:          88 45 ff                     mov    %al,0xffffffff(%ebp)   35:          88 55 fe                     mov    %dl,0xfffffffe(%ebp)   38:          8a 45 fe                     mov    0xfffffffe(%ebp),%al   3b:          02 45 ff                     add    0xffffffff(%ebp),%al   3e: 0f be c0                     movsbl %al,%eax   41:          c9                        leave    42:          c3                        ret    如果你精通汇编语言看完这段代码恐怕你已经口吐鲜血并晕倒在地了gcc居然生成了这么啰嗦的代码但是我们还是先说说C语言的函数调用规范吧。 我们已经看到了参数从右到左依次入栈。下面的说明全部以32Bytes代码为准其规范具体可罗列以下几条 l          调用者负责将参数压入堆栈顺序为从右到左依次入栈。也就是左边的最后入栈。 l          调用者使用near call指令将控制权传给被调用者。 l          被调用者得到控制权一般需要创建堆栈框架这不是必需的通常都是这么做。首先将ebp压入堆栈保存再将esp放入ebp使ebp成为访问参数的基址指针。 l          被调用者通过ebp访问参数。因为ebp已经先行压入堆栈所以[ebp4]就是被call指令自动压入堆栈的返回地址显然从[ebp8]开始就是参数。由于函数最左边的参数最后被压入堆栈所以[ebp8]就是该参数其他参数以此类推。像printf这样的函数具有个数不确定的参数但是参数入栈顺序的规则说明被调用者通过[ebp8]就能够找到第一个参数其他参数的类型和数目则需要由第一个参数给出。 l          被调用者减小esp的值为堆栈中的临时变量分配空间然后使用ebp和一个负的偏移访问。 l          被调用者使用alaxeax返回大小不同的值。浮点数可以通过ST0寄存器返回。 l          被调用者完成处理后使用事先建立的堆栈框架恢复espsbp的值并使用ret指令返回调用者。 l          调用者重新得到控制权通过给esp加上一个立即数清空堆栈尽量不要使用多次pop指令清空堆栈。如果因为使用了错误的函数原型通过堆栈多传递了或者少传递了参数调用者仍然能够将堆栈恢复到正确的状态因为调用者知道自己向堆栈压了几个字节的数据。 结合C语言的函数调用规则上面的代码不难理解。 从80386开始push指令的操作数可以是8-bit16-bit32-bit但是C语言统统按32-bit整型数处理被调用者也按32-bit进行处理。这一点很重要特别是汇编语言和C语言混合编程时。 9.         基本的数据类型间的转换 gcc处理三类基本数据类型 l          signed char , unsigned char  , 1 Byte l          signed short , unsigned short , 2 Bytes l          signed int , unsigned int , 4 Bytes 各种数据类型间的转换遵循一般C语言的规则具体可以参考IA-32的标准。这里只举一例说明 int main() { char ch’a’; int x2; int y-4; } 使用同样的方法进行编译及反汇编 00000000 main:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 18                    sub    $0x18,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c6 45 ff 61                   moVB   $0x61,0xffffffff(%ebp)   14:          c7 45 f8 02 00 00 00   movl   $0x2,0xfffffff8(%ebp)   1b:          c7 45 f4 fc ff ff ff        movl   $0xfffffffc,0xfffffff4(%ebp)   22:          c9                        leave    23:          c3                        ret    10.     gcc编译代码的基本运行环境 这一部分我查了很多的文档都没有这方面的介绍。又请教了很多的高手大致情况如下我实在无法保证这里所说的都是正确的并且将来也是正确的仅供参考 l          32-bit的保护模式下运行。 l          段寄存器CSdsesfsgsss必须指向同一段内存区域。 l          没有初始化的全局变量被放在BSS的段内该区域在代码段之后。但是如果你生成的文件是二进制文件BSS段不是该文件的一部分你需要自己小心使用。初始化的全局变量在DATA段内它是二进制文件的一部分并且位于代码段之后。被声明为const的全局变量被放在RODATA段内它也是二进制文件的一部分并放在代码段之后。 l          确保堆栈没有溢出小心代码段和全局数据不要被破坏。 我也查了Intel提供的帮助文档“Intel Architecture Software Developer’s Manual”一共有三卷之多参考了其中关于内存组织Volume 1:Memory Organization中的说法建议你去好好研究。总之使csdsss总是指向同一内存区域应该可以使代码正确运行。如果运行环境不是这样我就不知道结果了。 11.     访问外部的全局变量 看看在非C语言程序中如何访问C语言程序中的全局变量。如果你想使用其他程序加载C程序例如汇编语言写的程序这部分很有用特别是在核心开发时经常用到。 int myVal0x5; int main() { } 编译这段代码 gcc –c test.c ld –Ttext 0x0 –e main –N –oformat binary –Map memmap.txt –o test.bin test.o objdump –D –b binrary –m i386 test.bin 得到如下结果 00000000 .data:    0:          55                        push   %ebp    1:          89 e5                      mov    %esp,%ebp    3:          83 ec 08                    sub    $0x8,%esp    6:          83 e4 f0                     and    $0xfffffff0,%esp    9:          b8 00 00 00 00                mov    $0x0,%eax    e: 29 c4                      sub    %eax,%esp   10:          c9                        leave    11:          c3                        ret      12:          00 00                      add    %al,(%eax)   14:          05                        .byte 0x5   15:          00 00                      add    %al,(%eax) 全局变量myVal存储在0x14。刚才已经使用-Map开关使ld生成了内存映像文件memmap.txt应该能够找到 .data           0x00000014        0x4  *(.data .data.* .gnu.linkonce.d.*)  .data          0x00000014        0x4 test.o                 0x00000014                myVal 说明myVal位于test.o模块的0x00000014位置。使用地址作为偏移量就可以直接在其他语言中访问myVal变量了。另为也可以通过memmap.txt查到BSS段的大小 cat memmap.txt grep ‘/.bss’ grep ‘0x’ sed ‘s/.*0x/0x/’ 本例子BSS的大小是0x0。 无法直接访问C程序中的使用static修饰的全局变量。因为这样的变量是静态的map文件中没有列出他们的地址。也许你可以使用其他办法做到但是最好不要这样做。 12.     生成其他格式的二进制文件的选项 生成不同格式的二进制文件是一件相当麻烦的事。它需要使用很多不常使用的选项并且有些在man的帮助信息中没有被列出。 首先是gcc的选项-nostdinc。很显然使用该选项后gcc就不搜索默认的include路径了通常是/usr/include。如果需要使用的自定义的头文件可以使用-I选项添加搜索路径。 然后是ld的选项。第一个是-nostdlib就是忽略标准库。如果需要可以使用-L选项指定库的搜索路径。第二个是-Ttext就是指定代码段的地址如果没有继续指定其他段的地址则他们将自动的一次被放在代码段之后。第三个是-e就是指定代码的入口地址默认的是_start如果代码不是以其开头就应该指定入口点。第四个是—oformat binary就是输出的文件是原始的二进制文件而是如文件可以使系统支持的任何文件。但是中间模块文件不能是原始的二进制文件因为还需要很多符号和重定位信息。可以使用—iformat选项指定输入文件的格式但通常很少使用。第五个是-static如果使用了其他库用该使用静态链接方式除非你的程序支持动态链接。 另外还有代码指示伪指令。汇编器可以编译16-bit代码也可以编译32-bit代码。但是gcc总是生成32-bit的汇编代码。通过在C代码中使用asm()伪指令可以让gcc生成16-bit汇编代码。 第一个是.code16即生成在16-bit段中运行的16-bit代码 第二个是.code32即生成在32-bit段中运行的32-bit代码默认情况下gcc总是这么做 第三个是.code16gccgcc将根据需要决定生成在16-bit段下运行的16-bit或32-bit代码。GAS将会加上必要的前缀指示32-bit的指令或寄存器等。这个选项是很有用的它允许我们使用C语言写在16-bit环境下运行的代码不论是实模式还是保护模式。 现在可以在一个C模块中既有16-bit代码又有32-bit代码但是此时需要注意不同部分代码的地址空间问题。 例如我们想使用gcc生成在DOS下运行的.com程序和启动引导程序。 首先DOS中的.com文件是在实模式下运行的原始的二进制文件其起始地址为0x100。要使用gcc生成.com文件在每一个.c文件的开头加上如下伪指令 __asm__(“code16gcc/n”); 如果需要引用其他库文件则这些库文件也需要按这种方式生成。在链接时加上如下选项 -Ttext 0x100 –static –oformat binary 如果程序中包含嵌入的汇编代码需要将其转换为ATT格式。 如果要写引导程序只需要在链接时使用0x7C00代替0x100另外最终生成的二进制代码必须小于446个字节 13.     参考资料 l          Intel Architecture Software Developer’s Manual l          Manual Pages in Linux l          Redhat GNUPro Toolkit
http://www.lebaoying.cn/news/130607.html

相关文章:

  • 网站建设岗位的简介做得比较好的h5案例
  • 留言网站建设的报告南昌网站建设联系方式
  • 高级网站开发工程师证官网移动迷你世界
  • 广东网页制作网站网站需要多少钱
  • 外贸网站建设十大标准外贸网站建站免费在线自助建站
  • 什么网站做h5不收费上网站建设
  • 南宁网站建设速成培训班把网站做成静态页面
  • 请人做网站合同做火影网站背景图
  • 写作网站挣钱对比成都专业的网站建设公司
  • 网站开发求职信哎呀哎呀视频在线观看
  • 个人网页模板网站无锡新吴区建设局网站
  • 小辣椒网站开发湛江专业网站制作
  • 路得威网站谁做的建设电子商务网站步骤
  • 看电视剧的免费网站山东郓城住房和城乡建设厅网站
  • 搭建wordpress用哪种系统wordpress秒开优化
  • 中国文明网联盟网站建设python做的大型网站
  • 企业怎么建立网站凡科商城和有赞哪个好
  • 用了wordpress的电商网站海珠网站建设制作
  • it运维外包服务方案福建整站优化
  • 创业给企业做网站开发建立个人网站用虚拟主机
  • 精通网站建设 100O2O网站制作需要多少钱
  • 江苏宏澄建设有限公司网站百度推广怎么收费标准
  • 网站建设找祥赢wordpress做个米表
  • 北京企业网站建设公司哪家好单位网站建设内容
  • 二手车网站建设意见莆田网站建设制作
  • 如何建网站卖东西动漫网站设计与实现
  • 网站建设 慕课怎么注册公司域名邮箱
  • 电子及商务网站建设报告高端网站设计收费
  • 免费看网站源码苏州做网站哪家好
  • 免费行情软件网站下载大全爱从客户—管理者为某一公司做一份电子商务网站管理与维护的方案