I'm trying to write the following program to dump the interrupt vector table using FreeDOS in a virtual machine. I know that DEBUG will allow me to write an assembly program, but how do I create the following IVTDUMP.COM file, save it and run it?
Note: I'd like to try and do it all straight from FreeDOS if possible. I tried using the EDIT command but it errors out and I'm pretty sure I'm missing something.
for
(
address=IDT_255_ADDR;
address>=IDT_001_ADDR;
address=address-IDT_VECTOR_SZ,vector--
)
{
printf("%03d %08p ",vector,address);
__asm
{
PUSH ES
MOV AX,0
MOV ES,AX
MOV BX,address
MOV AX,ES:[BX]
MOV ipAddr,AX
INC BX
INC BX
MOV AX,ES:[BX]
MOV csAddr,AX
POP ES
};
printf("[CS:IP]=[%04X,%04X]\n",csAddr,ipAddr);
}
Things like for, address and printf are not part of assembly. You will have to rewrite that to actual assembly code or copy the macros and assembler you want to use to your freedos environment.
If you want to use debug as included in freedos you can use the a command to start writing assembly instructions, the n command to give a name and w to write the code to the file.
C:\debug
-a
06BC:0100 int 20
06BC:0102
-n ivtdump.com
-rcx 2
-w
Writing 0002 bytes.
-q
C:\
This sample program only exits the program through int 20. (The 2 after rcx indicates the length of the program to write to disk)
Related
I am recently porting a OpenGL API loader implemented by 64-bit masm to that of 32-bit, part of 64-bit source codes are as follows:
.code
extrn __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV: qword
glMultiDrawArraysIndirectBindlessCountNV proc
mov r11, __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV
jmp r11
glMultiDrawArraysIndirectBindlessCountNV endp
extrn __blue_glCore_glCopyTexImage1D: qword
glCopyTexImage1D proc
mov r11, __blue_glCore_glCopyTexImage1D
jmp r11
glCopyTexImage1D endp
...
e.g. external symbol __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV will be load when calling glMultiDrawArraysIndirectBindlessCountNV. My 32-bit modifications(change all qword to dword, all r11 to eax) are:
.model flat
.code
extrn __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV: dword
glMultiDrawArraysIndirectBindlessCountNV proc
mov eax, __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV
jmp eax
glMultiDrawArraysIndirectBindlessCountNV endp
extrn __blue_glCore_glCopyTexImage1D: dword
glCopyTexImage1D proc
mov eax, __blue_glCore_glCopyTexImage1D
jmp eax
glCopyTexImage1D endp
When other targets link this loader during compilation, the compiler(I used Visual Studio 2019) complains unresolved external symbol error. I actually know little about MASM, who can help me out?
Update1
I have created a mini demo in this repo to reproduce this problem, which can be built directly with Visual Studio and cmake. In particular, these lines puzzle me:
GLint major = 0, minor = 0;
//these two symbol are found
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
//this symbol is missed
glActiveTexture(0);
why only symbols of opengl1.0 and 1.1(opengl32.lib) loaded while others missed?
Update2
My Visual Studio linker complains:
Severity Code Description Project File Line Suppression State
Error LNK1120 1 unresolved externals test_bluegl E:\CPPCode\projects\bluegl\build\Debug\test_bluegl.exe 1
Error LNK2019 unresolved external symbol _glActiveTexture#4 referenced in function "private: virtual void __thiscall bluegl::BlueGLTest_GetVersion_Test::TestBody(void)" (?TestBody#BlueGLTest_GetVersion_Test#bluegl##EAEXXZ) test_bluegl E:\CPPCode\projects\bluegl\build\test_bluegl.obj 1
then I use dumpbin.exe to check generated symbol in bluegl.lib:
...
55DF0 _glActiveTexture#0
...
So I changed the corresponding proc to:
extrn __blue_glCore_glActiveTexture: dword
glActiveTexture proc param : dword
mov edx, __blue_glCore_glActiveTexture
jmp edx
glActiveTexture endp
Now the generated symbol was right and linking is OK, but new problems arose:
Visual Studio will report:
Severity Code Description Project File Line Suppression State
Error LNK2026 module unsafe for SAFESEH image. test_bluegl E:\CPPCode\projects\bluegl\build\bluegl.lib(BlueGLCoreWindowsImpl.obj) 1
Error LNK1281 Unable to generate SAFESEH image. test_bluegl E:\CPPCode\projects\bluegl\build\Debug\test_bluegl.exe 1
without setting /safeseh property for the masm source.
2 It's too heavy to append parameter list for each api, and I don't know why 64-bit masm not requiring parameter list.
Select a C implementation as workaround, but still interested in a masm32 implementation.
I have just got into ARM programming. Learned a few basics but am having issues with running code. I use VSCode on Linux Subsystem as my IDE.
I have nothing installed on my computer and i would like to run ARM code. I have read online something about "qemu" and "kernel" and stuff, but am not sure what they mean. It would be great if someone provides a detailed walkthrough for such a problem. I do not have a raspberry pi.
For example, how do i run the following division.s file on VSCode?
.global _start
_start:
MOV R1, #X
MOV R2, #Y
MOV R3, #Z
CMP R1, R2 # is x>y ?
BGT _tryx
CMP R2, R3 # is y>z ?
BGT _isy
MOV R4, R3
B _exit
_isy:
MOV R4, R2
B _exit
_tryx:
CMP R1, R3 # is x>z ?
BGT _isx
MOV R4, R3
B _exit
_isx:
MOV R4, R1
_exit:
MOV R0, R4
MOV R7, #1
SWI 0
.data
.equ X, 3
.equ Y, 5
.equ Z, 4
Are there any extensions i need to install? Is there anything i need to download? I have used gcc to compile C code. Can it be used here too?
Thx in advance! :D
Your question is rather a broad one. This being said, a slightly modified version of your program can be executed in WSL using the following procedure:
sudo apt-get install qemu-user
sudo mkdir -p /opt/arm/10
wget 'https://developer.arm.com/-/media/Files/downloads/gnu-a/10.2-2020.11/binrel/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz?revision=d0b90559-3960-4e4b-9297-7ddbc3e52783&la=en&hash=985078B758BC782BC338DB947347107FBCF8EF6B' -O gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz
sudo tar Jxf gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz -C /opt/arm/10
/tmp/division.s:
# count how often we can take Y from X
.global main
main:
MOV R1, #X
MOV R2, #Y
MOV R3, #0 # Q
_loop:
CMP R1, R2
BLT _exit
SUB R1, R2
ADD R3, #1
B _loop
_exit:
MOV R0, R3
MOV R7, #1
SWI 0
.data
.equ X, 23
.equ Y, 4
Compiling:
/opt/arm/10/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc -static -o /tmp/division /tmp/division.s
Executing - WSL:
qemu-arm /tmp/division
echo $?
5
Which is the expected result, since 23 div 4 is 5.
Executing - Windows 10:
C:\>c:\Windows\System32\bash -c "qemu-arm /tmp/division; echo $?"
5
C:\>
Or:
C:\>c:\Windows\System32\bash -c "qemu-arm /tmp/division"
C:\>echo %ERRORLEVEL%
5
Note that division.s may have been compiled in Windows 10 as well by downloading/installing gcc-arm-10.2-2020.11-mingw-w64-i686-arm-none-linux-gnueabihf.tar.xz instead of gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz - your choice.
I let it to you than to go into the details of using the information above for running your program from vscode, you question being a bit too broad IMHO.
Update: division.s was compiled statically on purpose for avoiding having to specify the locations for any non-needed dynamic libraries.
Compiling it without using the -static option, and executing it would result in the following error message to be displayed:
qemu-arm division
/lib/ld-linux-armhf.so.3: No such file or directory
It can be avoided by telling qemu-arm where to look for required dynamic libraries, /lib/ld-linux-armhf.so.3 in this case:
qemu-arm -L /opt/arm/10/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libc division
echo $?
5
That looks like a Linux program. And I guess you have an 64-bit x86 computer.
You want QEMU, specifically the executable qemu-arm which emulates an ARM processor running Linux on another Linux compatible system. In Debian derived Linux distributions it is in the package qemu-arm.
And on ebian derived Linux distributions for a compiler you can install the gcc-arm-linux-gnueabihf package for compiling for ARMv7 and ARMv8 with hardware floating point (Debian port name armhf), or gcc-arm-linux-gnueabi for some older ARMs with no hardware floating point Debian port name armel).
If you wish to install libraries, you need add the architecture to dpkg's list, for example:
dpkg --add-architecture armhf
How do you get the signature of an exported function of a DLL? I know this is possible since a program analysis tool such as IDA (and ollydbg) manages to get the following for GetVersionExA:
push offset VersionInformation ; lpVersionInformation
mov edi, offset dword_4D3B94
mov esi, offset aSS ; "%s - %s"
call GetVersionExA
Using a hex editor to search through PDBs, I could not find the string lpVersionInformation. So where and how can I extract the signature?
I'm attempting to write a function that prints strings the screen in C. It's for a boot loader so there are no external libraries or anything linked in. Here's my function:
void printString(const char* pStr) {
while(*pStr) {
__asm__ __volatile__ (
"movb 0x0e, %%ah\n"
"movb %[c], %%al\n"
"int $0x10\n"
:
: [c] "r" (*pStr)
: "ax"
);
++pStr;
}
}
When I run this, I don't get any errors in my VM. It just sits there with the cursor in the upper left corner of the screen. Any thoughts? I can produce an objdump -d if anyone thinks it will be helpful.
Okay after some helpful comments, I may just go with full assembly. Something like
Print:
push %ax
movb $0x0E, %ah # Set interrupt code
movb $0x00, %bh # Set page #
.loop:
lodsb # Load next char
test %al, %al # Check for \0
je .done
int $0x10 # Call interrupt
jmp .loop
.done:
pop %ax
ret
That should be 16-bit real mode compatible and can be assembled with GAS, which, as I understand it, works better than GCC for compiling 16-bit programs.
I think you're missing the point. The problem isn't your assembly code; the problem is that "int 10" is a BIOS
If you've already booted to an OS (e.g. Windows or Linux), then your x86 CPU is running in "protected mode"; and you probably don't have access to int 10 from user space ... unless something like a Windows command prompt emulates it for you.
As far as Linux/assembly programming in general, I strongly recommend this (free, on-line, very good) book:
Programming from the Ground Up, Jonathan Bartlett
Thank you for clarifying that you're writing a "boot loader". Strong suggestion1: boot your custom code from a USB stick, or create a virtual DOS floppy to boot a DOS VM (either VMWare or VBox VMs, for example).
Here are some tutorials:
http://www.codeproject.com/Articles/36907/How-to-develop-your-own-Boot-Loader
https://cs.au.dk/~sortie/dopsys/osdev/
http://wiki.osdev.org/Rolling_Your_Own_Bootloader
.model tiny
.code
org 100h
host:
mov ah,9
mov dx,offset hi
int 21h
mov ax,4c00h
int 21h
hi db 'HELLO'
end host
c: masm hello.asm
output of this says operand expected on line 1. Please tell me how to generate com files using this version of masm...
I know this is raising a long dead thread but I thought I'd chime in here as I could not find the answer to this online very easily.
Cannot be done with 5.1, however you can use EXE2BIN (just search on google) to convert it to a com file.
You can also use 6.11 which can be found at http://www.phatcode.net/downloads.php?id=175.
Once you have that running, your hello world app would be:
.MODEL TINY
.DOSSEG ; Make sure you are using dos segment CODE, DATA + STACK
.DATA
MSG DB "Hello, World!", 0Dh, 0Ah, '$'
.CODE
.STARTUP ; Setup the starting address otherwise you'll see:
; LINK : warning L4055: start address not equal to 0x100 for /TINY
MOV AH, 09h
MOV DX, OFFSET MSG
INT 21h
MOV AH, 4Ch
INT 21h
END
To compile: ML /AT HELLO.ASM (the /AT enables .MODEL TINY)
It should compile without warnings or errors tested on MASM 6.11 under MS-DOS 6.22 in DOSBOX.
Hope this helps someone who had the same issue as I.
It can be done in MASM 5.1 (or older). From the MASM 5.0 docs, here is the basic shell with your test program.
TITLE COMFILE
_TEXT SEGMENT
ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
ORG 100H
START:
mov ah,9
mov dx,offset hi
int 21h
mov ax,4c00h
int 21h
hi db 'HELLO','$'
_TEXT ENDS
END START
With the above file named COMFILE.ASM, assemble and convert to .com using the following steps:
A>MASM COMFILE;
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987. All rights reserved.
51668 + 464828 Bytes symbol space free
0 Warning Errors
0 Severe Errors
A>LINK COMFILE;
Microsoft (R) Overlay Linker Version 3.60
Copyright (C) Microsoft Corp 1983-1987. All rights reserved.
LINK : warning L4021: no stack segment
A>EXE2BIN COMFILE.EXE COMFILE.COM
Which should produce:
A>DIR COMFILE.COM
Volume in drive A has no label
Directory of A:\
COMFILE COM 18 01-01-80 12:00p
1 File(s) 30208 bytes free
A>COMFILE.COM
HELLO
A little thread necromancy here, yes. I also wasn't able to find a clear, working example of this elsewhere so hopefully this will help someone in the future.
MASM 6.0 was the first version of MASM capable of using the tiny memory model and therefore the first version of MASM capable of producing COM files. It's not terribly difficult to find copies of MASM 6.11 around the internet, and MASM 6.11 is still capable of being used under pure DOS if necessary.
Source: http://support.microsoft.com/kb/24954