小编Mic*_*tch的帖子

Bootloader在真实硬件上打印垃圾

我正在尝试编写自己的bootloader.虽然它在QEMU,Bochs和VirtualBox中运行良好,但我似乎无法在笔记本电脑上运行.

在我的笔记本电脑上,引导加载程序与所有模拟器的行为完全不同,挂起看似随机的地方,拒绝打印,甚至跳过一些jmp $指令.

虽然我对"真实硬件"有很多麻烦,但我认为它们都有一个原因.

以下代码是一个短引导加载程序,应该打印"TEST"消息3次,然后跳转到同一位置挂起:

[BITS 16]                                                                          
[ORG 0x7C00]                                                                                                    
    jmp 0x0000:start_16  ; In case bootloader is at 0x07C0:0x0000                                                             
start_16:                                                                          
    xor ax, ax                                                                 
    mov ds, ax                                                                 
    mov es, ax                                                                 
    cli                             ; Disable interrupts                       
    mov ss, ax                                                                 
    mov sp, 0x7C00                                                             
    sti                             ; Enable interrupts                        
    cld                             ; Clear Direction Flag                     
    ; Store the drive number                                                   
    mov [drive_number], dl                                                     
    ; Print message(s)                                                         
    mov si, msg                                                                
    call print_string                                                          
    mov si, msg                                                                
    call print_string                                                          
    mov si, msg                                                                
    call print_string                                                          

    jmp $   ; HALT                                                                                   

; …
Run Code Online (Sandbox Code Playgroud)

x86 assembly bios osdev bootloader

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

执行指令的数量与Hello World程序Nasm Assembly和C不同

我有一个简单的调试器(使用ptrace:http://pastebin.com/D0um3bUi)来计算给定输入可执行程序执行的指令数.它使用ptrace单步执行模式来计算指令.

为此,当程序1)的可执行文件(来自gcc main.c的a.out)作为输入提供给我的测试调试器时,它会在执行指令时打印大约100k.当我使用-static选项时,它会给出10681条指令.

现在在2)我创建一个汇编程序并使用NASM进行编译和链接,然后当这个可执行文件作为测试调试器输入时,它显示8个指令作为计数,哪个是apt.

程序1)中执行的指令数量很高,因为在运行时将程序与系统库链接起来了?使用-static并将计数减少1/10.如何确保指令计数仅是程序1)中主要功能的指令,以及程序2)为调试器报告的方式?

1)

#include <stdio.h>

int main()
{
    printf("Hello, world!\n");
    return 0;
}    
Run Code Online (Sandbox Code Playgroud)

我使用gcc来创建可执行文件.

2)

; 64-bit "Hello World!" in Linux NASM

global _start            ; global entry point export for ld

section .text
_start:

    ; sys_write(stdout, message, length)

    mov    rax, 1        ; sys_write
    mov    rdi, 1        ; stdout
    mov    rsi, message    ; message address
    mov    rdx, length    ; message string length
    syscall

    ; sys_exit(return_code)

    mov    rax, 60        ; sys_exit
    mov    rdi, …
Run Code Online (Sandbox Code Playgroud)

linux assembly gcc x86-64 nasm

5
推荐指数
2
解决办法
1198
查看次数

浪费内存分配局部变量

这是我的计划:

void test_function(int a, int b, int c, int d){
    int flag;
    char buffer[10];

   flag = 31337;
   buffer[0] = 'A';
}

int main() {
    test_function(1, 2, 3, 4);
}
Run Code Online (Sandbox Code Playgroud)

我用debug选项编译这个程序:

gcc -g my_program.c
Run Code Online (Sandbox Code Playgroud)

我使用gdb并使用intel语法反汇编test_function:

(gdb) disassemble test_function
Dump of assembler code for function test_function:
0x08048344 <test_function+0>:   push   ebp
0x08048345 <test_function+1>:   mov    ebp,esp
0x08048347 <test_function+3>:   sub    esp,0x28
0x0804834a <test_function+6>:   mov    DWORD PTR [ebp-12],0x7a69
0x08048351 <test_function+13>:  mov    BYTE PTR [ebp-40],0x41
0x08048355 <test_function+17>:  leave  
0x08048356 <test_function+18>:  ret    
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)

我拆卸了主要的:

(gdb) …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly gdb disassembly

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

自修改内存复制例程练习,6502 ASM

下面是我在 Commodore 64 上进行内存复制的自我修改例程。

我写了char codesnumber of repeats在一个表中,充满了screen_ram的这个套路。

我正在寻找优化建议。在这种情况下,我的优先事项是内存。

memCopy:    
  sourceAddress=*+1 ; mark self modifying addrres
fetchNewData:
  lda data_table    ; read char value into A
  ldx data_table+1  ; read repeat value into x
  inc sourceAddress     
  inc sourceAddress 

  cpx #00           ; if X=0 
  beq end           ; finish copying

  destination=*+1
- sta SCREEN_RAM
  inc destination
  dex
  bne -

  jmp fetchNewData

end:
  rts   

; data format:  <char>,<number of repeats>,[<char>,<number of repeats>,...],00,00

data_table: 
!by 01,03,02,02,......,00,00
Run Code Online (Sandbox Code Playgroud)

assembly 6502

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

汇编程序给出错误:/a.out:无法执行二进制文件:Exec格式错误

我是 64 位 x86 编码新手,但我运行的是 Ubuntu 14.04(可靠),并且我有一段非常简单的 64 位代码,我使用as进行汇编。我得到的输出具有奇怪的权限和文件类型。

当我跑步时:

as file.s
Run Code Online (Sandbox Code Playgroud)

我得到一个具有 770 权限的文件a.out

当我执行它时,我得到这个错误:

bash: ./a.out: 无法执行二进制文件: Exec 格式错误

当我跑步时:

file ./a.out 
Run Code Online (Sandbox Code Playgroud)

我得到:

./a.out:ELF 64 位 LSB 可重定位,x86-64,版本 1 (SYSV),未剥离

我使用的汇编代码是:

.section    .data
.LC0:
    .string "/bin/sh"

.LC1:
    .string "/bin/sh"

.LC3:
    .quad .LC1, 0

    .text
    .globl  _start
_start:
.LFB0:

    pushq   %rbp
    movq    %rsp, %rbp

    movq    $59,%rax     # System Call to execve
    movq    $.LC0, %rdi  # Pass program to execute
    movq    $.LC3, %rsi  # Pass command …
Run Code Online (Sandbox Code Playgroud)

x86 assembly x86-64 gnu-assembler ubuntu-14.04

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

这种交换在推送寄存器方面有多安全?

我是Assembly的新手,下面的代码应该通过两个不同的函数交换两个整数:首先使用swap_c然后再使用swap_asm.

但是,我怀疑,我是否需要push(我的意思是保存)汇编代码之前的每个寄存器值以及pop它们之后(就在返回之前main).换句话说,如果我在运行函数后返回不同的寄存器内容(不是像ebp或者esp只是eax,但是,只是ebx,ecx&edx),CPU会不会生我的气swap_asm?取消组装部件中的线条是否更好?

这段代码对我来说运行正常,我设法将27行汇编C代码减少到7个装配线.

ps:系统是Windows 10,VS-2013 Express.

main.c 部分

#include <stdio.h>

extern void swap_asm(int *x, int *y);

void swap_c(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

int main(int argc, char *argv[]) {
    int x = 3, y = 5;
    printf("before swap    => x = %d     y = …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly masm visual-studio

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

x86指令编码如何选择操作码

cmpw %ax -5x86-64的编码指令,来自Intel-instruction-set-reference-manual时,我有两个操作码可供选择:

3D iw CMP AX, imm16 I Valid Valid Compare imm16 with AX.
83 /7 ib CMP r/m16, imm8 MI Valid Valid Compare imm8 with r/m16.
Run Code Online (Sandbox Code Playgroud)

所以会有两个编码结果:

66 3d fb ff ; this for opcode 3d
66 83 f8 fb ; this for opcode 83
Run Code Online (Sandbox Code Playgroud)

那么哪一个更好?

我在下面尝试了一些在线反汇编程序

两者都可以反汇编到原点指令.但为什么6683fb00也有效,有效663dfb.

compiler-construction assembly x86-64 disassembly

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

如何将Spring Boot日志数据放入数据库?我想将所有信息和错误消息放入数据库

因此,我正在为应用程序创建管理面板,我想将所有用户问题和用户操作放入数据库,以便我可以在管理面板中显示它们。这样,管理员就不必去检查包含许多他们不需要使用的其他信息的日志文件。但我还需要自己的日志文件,以便我可以查看服务器是否发生了问题。

做到这一点的最佳方法是什么,如何在全局范围内设置这种日志记录,这样我就不必在每个控制器中手动将它们放入数据库?

java model-view-controller logging spring spring-boot

5
推荐指数
1
解决办法
2万
查看次数

我可以从MacOS的_start代码执行`ret`指令吗?Linux呢?

我想知道ret从程序的入口点返回是否合法.

NASM示例:

section .text
global _start
_start:
ret

; Linux: nasm -f elf64 foo.asm -o foo.o && ld foo.o
; OS X:  nasm -f macho64 foo.asm -o foo.o && ld foo.o -lc -macosx_version_min 10.12.0 -e _start -o foo
Run Code Online (Sandbox Code Playgroud)

ret 从堆栈中弹出一个返回地址并跳转到它.

但是堆栈的顶部字节是程序入口点的有效返回地址,还是我必须调用exit?

此外,上面的程序不会在OS X上发生段错误.它在哪里返回?

linux macos assembly return entry-point

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

键盘中断处理程序在系统ISO中不起作用

我正在尝试使用OSDev等编写操作系统。现在,我一直在制作键盘中断处理程序。当我编译操作系统并运行内核时,qemu-system-i386 -kernel kernel/myos.kernel一切运行正常。当我将所有内容放入ISO映像并尝试使用进行运行时qemu-system-i386 -cdrom myos.iso,当我按一个键时它将重新启动。我认为这是由我的中断处理程序中的某些问题或错误的IDT条目引起的。

我的键盘处理程序(AT&T语法):

.globl   keyboard_handler
.align   4

keyboard_handler:

    pushal
    cld 
    call keyboard_handler_main
    popal
    iret
Run Code Online (Sandbox Code Playgroud)

我在C中的主要处理程序:

void keyboard_handler_main(void) {
    unsigned char status;
  char keycode;
    /* write EOI */
    write_port(0x20, 0x20);

    status = read_port(KEYBOARD_STATUS_PORT);
    /* Lowest bit of status will be set if buffer is not empty */
    if (status & 0x01) {
        keycode = read_port(KEYBOARD_DATA_PORT);
        if(keycode < 0)
            return;

        if(keycode == ENTER_KEY_CODE) {
            printf("\n");
            return;
        }
        printf("%c", keyboard_map[(unsigned char) keycode]);
    }
} …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly osdev interrupt-handling

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