64位NASM CALL FAR 调用问题

太虚野老 2017-09-14 03:16:17
AMD处理器,64位环境,在NASM中,使用如下代码:
strlen_pointer:
dd test
dw 0x33
call far dword [strlen_pointer]
test:

编译通过,反汇编时生成的机器码也正确,但机器码的组织有问题,导致运行时出错:

我想实现的功能如下:

问题出在哪儿?
...全文
1998 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2019-06-28
  • 打赏
  • 举报
回复
不应该是qword吗
太虚野老 2017-09-21
  • 打赏
  • 举报
回复
这段测试代码在VS中可以运行,在IDA 的Windbg debugger中也可以运行,但是在IDA的Local Bochs debugger中运行时报错: 观察堆栈,可以看到RIP和CS并没有入栈: 应该入栈的RIP为0000000000401006:
太虚野老 2017-09-21
  • 打赏
  • 举报
回复
完整的测试代码: TITLE (test.asm) EXTERN MessageBoxA: proc .data text db 'Hello x64!', 0 caption db 'My First x64 Application', 0 strlen_pointer: dd _strlen dw code16_sel code16_sel equ 33H public main .code main : call fword ptr [strlen_pointer] mov rax,10000h ; RAX = 10000h add rax,40000h ; RAX = 50000h sub rax,20000h ; RAX = 30000h sub rsp,28h xor r9d,r9d lea r8, caption lea rdx, text xor rcx,rcx call MessageBoxA add rsp,28h ret _strlen: mov rax,10000h ;db 48h retf END ;END main,donot use main
  • 打赏
  • 举报
回复
我估计这是因为bochs是一个x86/x64仿真环境,并非真机调试,某些指令可能解释得有问题,只要原生环境能运行就可以。
  • 打赏
  • 举报
回复
public main, winmain .code main: winmain:
太虚野老 2017-09-20
  • 打赏
  • 举报
回复
不行: 1>LINK : error LNK2001: 无法解析的外部符号 main
  • 打赏
  • 举报
回复
把 main PROC main ENDP 两行删掉。
太虚野老 2017-09-20
  • 打赏
  • 举报
回复
不行,还是这个错误。
  • 打赏
  • 举报
回复
dd offset _strlen
太虚野老 2017-09-20
  • 打赏
  • 举报
回复
下面是我写的一段MASM的代码,但是编译时报错: TITLE (test.asm) TITLE 在IDA PRO中调试时,需使用Local Bochs debugger EXTERN MessageBoxA: proc .data text db 'Hello x64!', 0 caption db 'My First x64 Application', 0 strlen_pointer: dd _strlen dw code16_sel code16_sel equ 33H .code main PROC call fword ptr [strlen_pointer] mov rax,10000h ; RAX = 10000h add rax,40000h ; RAX = 50000h sub rax,20000h ; RAX = 30000h sub rsp,28h xor r9d,r9d lea r8, caption lea rdx, text xor rcx,rcx call MessageBoxA add rsp,28h ret _strlen: mov rax,10000h db 48h retf ;call ExitProcess main ENDP END ;END main,donot use main 错误信息: 1>test.asm(10): error A2006: undefined symbol : _strlen
  • 打赏
  • 举报
回复
我试了一下,nasm只要直接call far [xxx]就可以,masm需要call fword ptr [xxx]。 需要注意的是不论nasm、masm在64位模式下的far return指令都没有生成rex.w前缀,必须手工补上才能正确返回。 另外,虽然intel手册上说了call far m16:32在64位模式下可用,但实测会产生异常,即便连接时用/largeaddressaware:no限制加载在4GB以上地址也不行。必须要用call far m16:64才行,而该指令在amd64处理器上并不支持。amd64上不支持80位far地址,只认48位far地址。 global _start section .data use64 farptr: dq test1 ; for intel64 only dw 33h section .code use64 _start: call far [farptr] ret test1: db 48h retf
太虚野老 2017-09-17
  • 打赏
  • 举报
回复
引用 2 楼 DelphiGuy 的回复:
呃,MASM/TASM要用call fword ptr [strlen_pointer]
请给出在64位MASM中实现该功能的完整代码清单。
太虚野老 2017-09-16
  • 打赏
  • 举报
回复
fword 编译出错: 1>x64Nasm.asm(15): error : comma, colon, decorator or end of line expected after operand
  • 打赏
  • 举报
回复
呃,MASM/TASM要用call fword ptr [strlen_pointer]
  • 打赏
  • 举报
回复
应该是call fword [strlen_pointer]
Linux下AT&T汇编语法格式简介 一、AT&T 格式Linux 汇编语法格式 在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。例如: AT&T 格式 Intel 格式 pushl %eax push eax 在 AT&T 汇编格式中,用 '$' 前缀表示一个立即操作数;而在 Intel 汇编格式中,立即数的表示不用带任何前缀。例如: AT&T 格式 Intel 格式 pushl $1 push 1 AT&T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。在 Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边。例如: AT&T 格式 Intel 格式 addl $1, %eax add eax, 1 在 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀'b'、'w'、'l'分别表示操作数为字节(byte,8 比特)、字(word,16 比特)和长字(long,32比特);而在 Intel 汇编格式中,操作数的字长是用 "byte ptr" 和 "word ptr" 等前缀来表示的。例如: AT&T 格式 Intel 格式 movb val, %al mov al, byte ptr val 在 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上'*'作为前缀,而在 Intel 格式中则不需要。 远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为 "ljump" 和 "lcall",而在 Intel 汇编格式中则为 "jmp far" 和 "call far",即: AT&T 格式 Intel 格式

21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧