我如何组装GAS组装和与开放在Watcom C库链接呢? [英] How do I assemble GAS assembly and link it with the Open Watcom C library?

查看:314
本文介绍了我如何组装GAS组装和与开放在Watcom C库链接呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图产生16位DOS可执行文件,但使用gcc编译器。所以,我使用的是古老的GCC-4.3 IA16端口。我做了我构建一个码头工人形象: HTTPS://registry.hub。 docker.com/u/ysangkok/ia16-gcc-rask

下面就是我想:

 主机$的mkdir结果
主持人$搬运工运行-v $ PWD /结果:/结果 - 它ysangkok / IA16-GCC-拉斯克
集装箱$ CD结果

我不包括头,导致GCC不能使用OpenWatcom的libc中的头。

 容器$回声'的main(){printf的(笑); }'> test.c的

我不链接,因为我没有可用的16位的binutils。如果我建立一个目标文件,这是不正确标记为16位。

 容器$ /干线/建造-IA16主/ preFIX /斌/ IA16-未知精灵-GCC -S test.c的

现在我有这样的汇编文件:

  .arch i8086,跳跃
    。code16
    .att_syntax preFIX
#NO_APP
    .section伪.RODATA
.LC0:
    .string笑
    。文本
    .p2align 1
    。全球主要
    .TYPE为主,@function
主要:
    PUSHW%基点
    MOVW%SP,BP%
    SUBW $ 4%SP
    调用__main
    MOVW $ .LC0,斧头%
    PUSHW%斧
    调用printf
    ADDW $ 2,SP%
    MOVW%BP,SP%
    POPW%基点
    RET
    .size为主,。,主
    .identGCC(GNU)4.3.0 20070829(实验)

在容器外,在主机,我尝试用YASM组装它:

 %YASM -m -p 86 -f气-o精灵test.o test.s
test.s:1:警告:指令`.arch'无法识别
test.s:3:错误:垃圾在行结束,第一个无法识别的字符是'P'

我注释掉的语法线以来YASM不理解它,然后再试一次,这次它成功了。

我测试搬迁符号:

  objdump的%-r test.otest.o:文件格式ELF32-I386RELOCATION记录[.text段]:
OFFSET类型值
00000007 R_386_PC16 __main
0000000A R_386_16 .RODATA
0000000e R_386_PC16的printf

可悲的是,他们是32位。当我尝试和容器反正链接,这是行不通的:

 根@ 1341f35c4590:/#CD流/ BINL /
根@ 1341f35c4590:/流/ BINL#WATCOM = /流/流/ BINL /万联科
打开在Watcom链接器1.9版
部分版权所有(C)1985-2002 Sybase,Inc.保留所有权利。
来源$ C ​​$ c中的开放的Sybase公众在Watcom许可证下是可用的。
见http://www.openwatcom.org/了解详情。
preSS CTRL / D完成
万联科> DOS系统
万联科>文件/results/test.o
[评论:我的下一行preSS控制-D]
万联科>加载目标文件
警告! W1080:文件/results/test.o是一个32位对象文件
错误! E2015:文件/results/test.o(test.s):指定坏定位类型
错误! E2015:文件/results/test.o(test.s):指定坏定位类型
错误! E2015:文件/results/test.o(test.s):指定坏定位类型

如果我试图做一个COFF而不是ELF的,YASM甚至无法装配:

 根@ 1341f35c4590:/#CD流/ BINL /
根@ 1341f35c4590:/流/ BINL#WATCOM = /流/流/ BINL /万联科
打开在Watcom链接器1.9版
部分版权所有(C)1985-2002 Sybase,Inc.保留所有权利。
来源$ C ​​$ c中的开放的Sybase公众在Watcom许可证下是可用的。
见http://www.openwatcom.org/了解详情。
preSS CTRL / D完成
万联科> DOS系统
万联科>文件/results/test.o
万联科>加载目标文件
警告! W1080:文件/results/test.o是一个32位对象文件
错误! E2015:文件/results/test.o(test.s):指定坏定位类型
错误! E2015:文件/results/test.o(test.s):指定坏定位类型
错误! E2015:文件/results/test.o(test.s):指定坏定位类型

我知道YASM不支持16位,但也许有一个解决方法吗?是否有气体兼容的16位汇编?气到英特尔转换器不工作。


解决方案

我的不可以专家,但据我所知没有16位兼容GAS汇编。

此外GCC从来就产生8086的16位code。该拉斯克港产16位code中的
该操作数大小为16位默认。因此,像 MOV AX,1234H 发出为 B8 34H 12H ,而不是 66的指令B8 34H 12H 这将是
除$ P $实模式PTED为 MOV EAX,xxxx1234h (如果您对80386 +运行)

为地址模式同样的事情。

的问题是,这仅仅是code时,对象的文件格式仍是32位,所以他们是为了由32位工具最终用于在使用中使用
V86的环境。
ELF例如不支持16位的搬迁,也不会COFF(根据NASM)。

因此​​,即使GCC和GAS产生16位code,他们只输出相对较新的目标格式。
给定一个目标文件创建一个MZ或COM可执行每个工具在这些格式之前创建的,并且不支持他们。
任何努力都用在增加新格式的支持,因为DOS停止很久以前就被使用。


非常长的变通办法(并不意味着被使用)

我只能像二,非常非常难,方式使用GCC编译器。


  1. 尝试移植到NASM。 NASM支持超过YASM(再次旧的16位格式已被丢弃)更为输出文件格式。

组装与 -masm =英特尔标记的源文件,以获得英特尔的语法。然后,你需要GAS点指令转换成NASM指令的工具。
这需要手动为codeD 的。他们大多是简单的替换,比如。全球 XXX为 GLOBAL XXX ,但你需要转换的有效地址,
添加 EXTERN XXX 未定义功能。

<醇开始=2>
  • 请自行搬迁。 (您需要与IA16架构和DOS下熟练)

  • 您不能使用任何外部符号,并产生PIC code( -fPIC 标志)和原始二进制(即只是code)。
    定义函数指针的结构,一个是你需要使用的每个外部函数,像


    结构context_t
    {
        INT(*的printf)(字符*格式,...);
        ...
    };


    然后声明一个指针 context_t ,说 context_t * CTX ;
    如果你需要使用像 A printf函数使用则将ctx->的printf 来代替。
    编译code。

    现在创建一个C源代码,称之为装载机,定义类型 context_t 的一个变量,并初始化它的指针。
    loader然后必须读取二进制文件中,找到分配给 CTX 指针空间,并将其设置为 context_t 变量,则
    加载在内存中(在段边界)的二进制文件,并与远调用执行它。

    您需要找到文件中的指针的位置,你可以使用GCC( -Xlinker -Map = output.map 开关)或生成的地图文件使用签名
    像旧的BIOS PCI 32bit的服务($ PCI签名),并扫描它。
    要注意的是海湾合作委员会中产生的code规定其他限制,但PIC开关应尽量减少这一点。
    您可以追加事件的二进制文件的加载器(如果你使用MZ格式和心灵对准谨防)后,简化的东西。

    I am trying to produce 16-bit DOS executables, but using the gcc compiler. So I am using the ancient gcc-4.3 ia16 port. I made a Docker image of my build: https://registry.hub.docker.com/u/ysangkok/ia16-gcc-rask

    Here's what I am trying:

    host $ mkdir results
    host $ docker run -v $PWD/results:/results -it ysangkok/ia16-gcc-rask
    container $ cd results
    

    I don't include the header, cause gcc can't use OpenWatcom's libc headers.

    container $ echo 'main() { printf("lol"); }' > test.c
    

    I don't link cause I don't have 16-bit binutils available. If I build an object file, it isn't correctly marked as 16-bit.

    container $ /trunk/build-ia16-master/prefix/bin/ia16-unknown-elf-gcc -S test.c
    

    Now I have this assembly file:

        .arch i8086,jumps
        .code16
        .att_syntax prefix
    #NO_APP
        .section    .rodata
    .LC0:
        .string "lol"
        .text
        .p2align    1
        .global main
        .type   main, @function
    main:
        pushw   %bp
        movw    %sp,    %bp
        subw    $4, %sp
        call    __main
        movw    $.LC0,  %ax
        pushw   %ax
        call    printf
        addw    $2, %sp
        movw    %bp,    %sp
        popw    %bp
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.3.0 20070829 (experimental)"
    

    Outside the container, in the host, I try to assemble it with yasm:

     % yasm -m x86 -p gas -f elf -o test.o test.s  
    test.s:1: warning: directive `.arch' not recognized
    test.s:3: error: junk at end of line, first unrecognized character is `p'
    

    I comment out the syntax line since yasm doesn't understand it, and try again, this time it succeeds.

    I test the relocation symbols:

     % objdump -r test.o
    
    test.o:     file format elf32-i386
    
    RELOCATION RECORDS FOR [.text]:
    OFFSET   TYPE              VALUE 
    00000007 R_386_PC16        __main
    0000000a R_386_16          .rodata
    0000000e R_386_PC16        printf
    

    Sadly they are 32-bit. When I try and link anyway in the container, it doesn't work:

    root@1341f35c4590:/# cd ow/binl/
    root@1341f35c4590:/ow/binl# WATCOM=/ow /ow/binl/wlink 
    Open Watcom Linker Version 1.9
    Portions Copyright (c) 1985-2002 Sybase, Inc. All Rights Reserved.
    Source code is available under the Sybase Open Watcom Public License.
    See http://www.openwatcom.org/ for details.
    Press CTRL/D to finish
    WLINK>system dos
    WLINK>file /results/test.o
    [ comment: i press control-d on the next line ]
    WLINK>loading object files
    Warning! W1080: file /results/test.o is a 32-bit object file
    Error! E2015: file /results/test.o(test.s): bad relocation type specified
    Error! E2015: file /results/test.o(test.s): bad relocation type specified
    Error! E2015: file /results/test.o(test.s): bad relocation type specified
    

    If I try and make a COFF instead of an ELF, yasm can't even assemble:

    root@1341f35c4590:/# cd ow/binl/
    root@1341f35c4590:/ow/binl# WATCOM=/ow /ow/binl/wlink 
    Open Watcom Linker Version 1.9
    Portions Copyright (c) 1985-2002 Sybase, Inc. All Rights Reserved.
    Source code is available under the Sybase Open Watcom Public License.
    See http://www.openwatcom.org/ for details.
    Press CTRL/D to finish
    WLINK>system dos
    WLINK>file /results/test.o
    WLINK>loading object files
    Warning! W1080: file /results/test.o is a 32-bit object file
    Error! E2015: file /results/test.o(test.s): bad relocation type specified
    Error! E2015: file /results/test.o(test.s): bad relocation type specified
    Error! E2015: file /results/test.o(test.s): bad relocation type specified
    

    I know yasm doesn't support 16-bit, but maybe there is a workaround? Is there a GAS-compatible 16-bit assembler? The GAS-to-Intel converters are not working.

    解决方案

    I'm not an expert but AFAIK there are no 16 bit GAS compatible assemblers.

    Furthermore gcc was never meant to produce 8086 16 bit code. The Rask port produce 16 bit code in the sense that the operand size is 16 bit by default. So an instruction like mov ax, 1234h is emitted as b8 34h 12h rather than as 66 b8 34h 12h which will be interpreted as mov eax, xxxx1234h in real mode (if you run on 80386+)

    Same thing for the address mode.

    The problem is that this is just the code, the object file formats are still for 32 bit, so they are meant to be used by 32 bit tools eventually for use in a v86 environment. ELF for example don't support 16 bit relocation, nor COFF does (according to nasm).

    So even GCC and GAS produce 16 bit code they output only relatively new object format. Every tools that given an object file create a MZ or COM executable was created before these formats and don't support them. No efforts have been spent on adding support to new formats as DOS ceased to be used long time ago.


    Very long Workarounds (not meant to be used)

    I can only image two, very very hard, way to use gcc as a compiler.

    1. Try porting to NASM. NASM support far more output file format than YASM (again old 16 bit format have been dropped).

    Assemble the source file with -masm=intel flag to get Intel syntax. Then you need a tool to convert GAS dot directives to NASM directives. This have to be coded manually. Most of them are simple substitutions like .global XXX to GLOBAL XXX but you need to convert effective addresses and add EXTERN XXX for undefined functions.

    1. Do the relocations yourself. (You need to be skilled with IA16 architecture and DOS)

    You must not use any external symbol and produce PIC code (-fPIC flag) and a raw binary (i.e. just code). Define a struct of function pointers, one for each external function you need to use, something like

    struct context_t
    {
        int (*printf)(char* format, ...); 
        ...
    };
    

    Then declare a pointer to context_t, say context_t* ctx; If you need to use a function like printf use ctx->printf instead. Compile the code.

    Now create a C source, call it loader, that define a variable of type context_t and initialize its pointers. The loader then must read the binary file, locate the space allocated for the ctx pointer and set it to the address of its context_t variable, then load the binary file in memory (at segment boundary) and execute it with a far call.

    You need to find the position of the pointer in the file, you can use a map file generated by GCC (-Xlinker -Map=output.map switch) or use a signature like the old BIOS PCI 32bit service (the $PCI signature) and scan for it. Beware that the code generated by GCC may impose other constraints, but the PIC switch should minimize this. You can event append the binary file after the loader (beware if you use MZ format and mind the alignment) and simplify things.

    这篇关于我如何组装GAS组装和与开放在Watcom C库链接呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆