标签: gnu-assembler

有没有办法使用其他二进制文件中的全局符号而不将其链接到

我正在尝试将游戏转换为苏联 PDP11 兼容机。由于它有严格的内存限制 - 56K RAM,我必须在运行时加载部分代码。这意味着我需要构建几个相互交叉引用符号的二进制模块。我用的是GAS和LD。

有没有办法仅使用这些工具来完成此任务?

例如,一个二进制模块文件想要加载另一个二进制模块,为此它必须知道另一个二进制文件的大小。尺寸可以作为符号使用,如下所示:

.title OtherModule

begin:
  some code
end:

.equiv SizeOfTheOtherModuleInWords, ((end - begin) / 2)
Run Code Online (Sandbox Code Playgroud)

另一个例子,游戏中的每个级别单独加载,并包含从始终驻留在内存中的主引擎调用子例程的代码。


我通过链接器脚本找到了解决方案。我可以使用/DISCARD/部分从链接中排除文件。

OUTPUT_FORMAT("binary")
OUTPUT_ARCH(pdp11)

INPUT(core.o bootstrap.o)
OUTPUT(AKU.SAV)

FileSizeCoreWords = ((FileEndCore - FileBeginCore) / 2);

SECTIONS
{
    . = 0;
.text :
    {
        bootstrap.o (.text)
    }
.data :
    {
        bootstrap.o (.data)
    }
.bss :
    {
        bootstrap.o (.bss)
    }
/DISCARD/ :
    {
        core.o
    }
}
Run Code Online (Sandbox Code Playgroud)

assembly gnu-assembler ld

1
推荐指数
1
解决办法
326
查看次数

不支持的指令“mov”

我正在研究基本的 shell 代码和orw代码。
但是,在此过程中,我收到以下错误消息:

错误:不支持的指令mov

这是我的 C 和汇编代码框架:

// File name: orw.c
// Compile: gcc -o orw orw.c -masm=intel

__asm__(

    ".global run_sh\n"
    "run_sh:\n"

    "push 0x67\n"
    "mov rax, 0x616c662f706d742f \n"
    "push rax\n"
    "mov rdi, rsp\n"
    "xor rsi, rsi\n"
    "xor rdx, rdx\n"
    "xor eax, eax\n"
    "mov eax, 2\n"
    "syscall"
    "\n"
    "mov rdi, eax\n"
    "mov rsi, rsp\n"
    "sub rsi, 0x30\n"
    "mov rdx, 0x30\n"
    "xor eax, eax\n"
    "syscall"
    "\n"
    "mov rdi,1\n"
    "mov eax,1\n"
    "syscall" 
);

void run_sh();

int main() { run_sh(); …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 gnu-assembler inline-assembly att

1
推荐指数
1
解决办法
1839
查看次数

如何在 x64 和 x32 的 intel 语法中跳转到内存位置

我如何跳转到 intel 汇编语法(x32 和 x64)中的已知内存地址。

我想我已经掌握了 64 位语法。例如,如果在 x64 中我想跳转到位于 的代码0x75767并且我位于0000,我会这样做:

0000: FF 25 01 00 00 00         jmp QWORD PTR [rip+0x75761]
Run Code Online (Sandbox Code Playgroud)

^ 正确吗?我想我可以使用 objdump 将这些字节分解为 x32 指令,objdump.exe -D -Mintel,i386 -b binary -m i386 test.bin结果是:

jmp    DWORD PTR 0x75761
Run Code Online (Sandbox Code Playgroud)

然后只需使用clang++.exe -masm=intel -m32 -c test.o将此指令转换为 x32 字节即可,但它显示:

error: invalid operand for instruction
jmp DWORD PTR 0x75761
^
Run Code Online (Sandbox Code Playgroud)

我想避免写入任何寄存器。

我的 x64 jmp 指令正确吗?

我如何在 x32 中完成类似的事情?假设在 x32 中我需要跳转到0x400107并且我在0x400000

我正在调整 Windows 上的运行进程内存。如果我的问题有不准确的地方,请原谅我,我正在学习。

x86 assembly x86-64 gnu-assembler clang

1
推荐指数
1
解决办法
1239
查看次数

GAS程序集片段除以0,不确定原因

我有以下功能,涉及GAS语法中的i386程序集片段:

inline int MulDivRound(
    int nNumber,
    int nNumerator,
    int nDenominator )
{
    int nRet, nMod;

    __asm__ __volatile__ (
        "mov    %2,     %%eax   \n"
        "mull   %3              \n"
        "divl   %4              \n"
        "mov    %%eax,  %0      \n"
        "mov    %%edx,  %1      \n"

        :   "=m"    (nRet),
            "=m"    (nMod)
        :   "m"     (nNumber),
            "m"     (nNumerator),
            "m"     (nDenominator)
        :   "eax", "edx"
    );

    return nRet + nMod*2 / nDenominator;
}
Run Code Online (Sandbox Code Playgroud)

我注意到,在一些情况下,我正在EXC_I386_DIV使用此功能崩溃.以下调用会产生这样的崩溃:

int res = MulDivRound( 4096, -566, 400 );
Run Code Online (Sandbox Code Playgroud)

我无法清楚地看到正在发生的事情导致此函数除以0:当然它只是移动4096 eax,然后乘以-566,然后将其除以400,返回除法运算结果的两个分量.任何人都可以对此有所了解吗?

x86 assembly gnu-assembler divide-by-zero i386

0
推荐指数
1
解决办法
318
查看次数

无法理解启用GDT分段,即更新CS寄存器

我目前正在遵循启用GDT细分的指南.我正在使用GNU Assembler和Bochs进行仿真.

我知道我需要使用GDT描述符加载GDT寄存器.我已经完成了,接下来的步骤是将所有具有相对于GDT的偏移的段寄存器加载到代码/数据段描述符的各个位置.这样做的代码如下:

reloadSegments:
   ; Reload CS register containing code selector:
   JMP   0x08:reload_CS ; 0x08 points at the new code selector
.reload_CS:
   ; Reload data segment registers:
   MOV   AX, 0x10 ; 0x10 points at the new data selector
   MOV   DS, AX
   MOV   ES, AX
   MOV   FS, AX
   MOV   GS, AX
   MOV   SS, AX
   RET
Run Code Online (Sandbox Code Playgroud)

但是,我无法理解如何可以隐式加载具有偏移量的CS寄存器,而不会显着跳跃到CS:IP对指向的任何内存位置 - 即,如果代码段描述符位于GDT_start + 0x10,我尝试将0x10加载到CS寄存器,虚拟机跳转到0x10:IP,我从不输入.reload_CS标签.

我的例程版本(at&t语法):

_start:
    // Disable interrupts
    cli
    // Load GDT register with location of GDT
    lgdt    0x3c

    // Load location of Code …
Run Code Online (Sandbox Code Playgroud)

x86 assembly gnu-assembler osdev

0
推荐指数
1
解决办法
741
查看次数

GNU as, puts 有效,但 printf 无效

这是我现在正在玩的代码:

# file-name: test.s
# 64-bit GNU as source code.
    .global main

    .section .text
main:
    lea message, %rdi
    push %rdi
    call puts

    lea message, %rdi
    push %rdi
    call printf

    push $0
    call _exit

    .section .data
message: .asciz "Hello, World!"
Run Code Online (Sandbox Code Playgroud)

编译说明:gcc test.s -o test

修订版 1:

    .global main
    .section .text
main:
    lea message, %rdi
    call puts

    lea message, %rdi
    call printf

    mov $0, %rdi
    call _exit

    .section .data
message: .asciz "Hello, World!"
Run Code Online (Sandbox Code Playgroud)

最终修订版(作品):

    .global main
    .section .text
main:
    lea message, %rdi …
Run Code Online (Sandbox Code Playgroud)

64-bit x86 assembly gnu-assembler crt

0
推荐指数
1
解决办法
681
查看次数

Undefined reference to 'esp'

链接目标文件时,我得到了对“ esp”的未定义引用。

我在名为mydc.s的文件中编写了汇编代码

然后我使用创建了目标文件

as --32 -march=i386 mydc.s -o mydc.o

(这里没有错误)然后将其与

gcc -m32 -march=i386 mydc.o -o mydc

然后它创建错误消息为

(.text + 0x2a):对'esp'的未定义引用

代码如下

    .section ".text"


    .globl  main
    .type   main,@function

main:

    pushl   %ebp
    movl    %esp, %ebp


input:

    pushl   $buffer 
    pushl   $scanfFormat
    call    scanf
    addl    $8, %esp

    ## check if user input EOF
    cmp $EOF, %eax
    je  quit

    pushl   $buffer
    call    isdigit
    addl    $4, esp
    cmp $1, %eax
    je  if_digit

    movl    buffer, %eax

    cmpl    $'p', %eax
    je  if_p

    cmpl    $'q', %eax
    je  if_q …
Run Code Online (Sandbox Code Playgroud)

x86 assembly gnu-assembler att

0
推荐指数
1
解决办法
95
查看次数

x86_64 无法将 64 位值添加到 rax,“'add' 上的操作数不匹配”

我正在尝试组装一些 64 位代码,但组装失败了:

addq $0xffffff7fc0005000, %rax
Run Code Online (Sandbox Code Playgroud)

有错误:

`add' 的错误操作数类型不匹配

第一个操作数是一个 64 位值,后者是一个应该组装好的寄存器。该指令前面有一个.code64伪操作。我正在组装

x86_64-elf-as test.s -o test.o --64
Run Code Online (Sandbox Code Playgroud)

至于汇编器本身,当用--version它调用时返回:

GNU assembler (GNU Binutils) 2.32
Copyright (C) 2019 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `x86_64-elf'.
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 gnu-assembler immediate-operand

0
推荐指数
1
解决办法
246
查看次数

在汇编文件中包含头文件

我试图将包含宏的头文件包含到我的主程序集文件中,但编译失败。

下面是我的main.S文件

#include "common.h"
BEGIN
    mov $0x0E40, %ax
    int $0x10
    hlt
Run Code Online (Sandbox Code Playgroud)

以下是我的common.h文件:

.macro BEGIN
    LOCAL after_locals
    .code16
    cli
    ljmp $0, $1f
    1:
    xor %ax, %ax
    /* We must zero %ds for any data access. */
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs
    mov %ax, %bp
    /* Automatically disables interrupts until the end of the next instruction. */
    mov %ax, %ss
    /* We should set SP because BIOS calls may depend on …
Run Code Online (Sandbox Code Playgroud)

assembly gcc gnu gnu-assembler att

0
推荐指数
1
解决办法
8250
查看次数

鉴于前两个参数是动态数组,如何访问函数的最后一个参数的值?

C中的函数是

void f(int* out, int* in, int nbElements){
    // do stuff
}
Run Code Online (Sandbox Code Playgroud)

由于int nbElements是第一个被压入堆栈in并且out具有可变大小,我如何访问 的值nbElements?据我了解,堆栈看起来像这样:

          esp
          ebp
     return address         # -4(%ebp) 
1st element of int* out     # -8(%ebp)
1st element of int* in      # (%ebp - 8 - 4*nbElements)
      nbElements            # not sure how I can access the value of this
Run Code Online (Sandbox Code Playgroud)

那么如何在nbElements不知道其地址的情况下访问的值呢?

x86 assembly gnu-assembler calling-convention att

0
推荐指数
1
解决办法
55
查看次数

GCC 是否优化汇编源文件?

我可以使用 GCC 将汇编代码文件转换为可重新分配的文件。

gcc -c source.S -o object.o -O2
Run Code Online (Sandbox Code Playgroud)

优化选项是否有效?我可以期望 GCC 优化我的汇编代码吗?

c assembly gcc gnu-assembler compiler-optimization

0
推荐指数
1
解决办法
359
查看次数