anol
anol

Reputation: 9115

Checking whether a given assembly file should run on a given processor

I'd like to assembly an x86 file while ensuring that the code will run on a given processor, without having to test it on a processor emulator.

Is there a tool/technique which would allow me to do some sort of x86 instruction classification according to the oldest required processor that supports it, or at least to warn me if incompatible instructions are being used?

In short, I'm looking for an automated version of this Wikipedia table of x86 instruction listings, to help me check if a given code should be compatible with a given processor.

Upvotes: 2

Views: 273

Answers (2)

Peter Cordes
Peter Cordes

Reputation: 365971

I ran into this problem when booting 32bit Ubuntu GNU/Linux on an old Athlon XP. A few programs died with SIGILL (illegal instruction).

I assume Ubuntu compiles even 32bit code with -mfpmath=sse, and the programs that crashed were using double-precision floating point (i.e. SSE2). Athlon XP doesn't support SSE2. AMD64 k8 CPUs were the first AMD CPUs to support it.

Look for movsd / addsd / comisd in the disassembly. (s = scalar, d = double. There could also be movapd / movupd / addpd / etc. (p = packed). grep (or search in less) for [sp]d .*%xmm, and that should probably find any SSE2 instructions. packed 32bit int instructions also tend to end with d (e.g. pshufd), but those are SSE2 or higher as well.

As @nrz correctly points out, not every instruction in a program will run. Also, some parts of the .text segment may actually be data, not code. Still, look for the CPUID instruction in disassembly output to see if the program checks what kind of CPU it's running on.

I do like @Michael's idea of disassembling to a temp file, adding a CPU limitation, and then checking for errors when you assemble.

Upvotes: 0

Michael
Michael

Reputation: 58507

In short, I'm looking for an automated version of this Wikipedia table of x86 instruction listings, to help me check if a given code should be compatible with a given processor.

You could emit a temporary assembly file with the following directive:

[CPU level]

Where level is one of:

  • 8086 Assemble only 8086 instruction set
  • 186 Assemble instructions up to the 80186 instruction set
  • 286 Assemble instructions up to the 286 instruction set
  • 386 Assemble instructions up to the 386 instruction set
  • 486 486 instruction set
  • 586 Pentium instruction set
  • PENTIUM Same as 586
  • 686 P6 instruction set
  • PPRO Same as 686
  • P2 Same as 686
  • P3 Pentium III (Katmai) instruction sets
  • KATMAI Same as P3
  • P4 Pentium 4 (Willamette) instruction set
  • WILLAMETTE Same as P4
  • PRESCOTT Prescott instruction set
  • X64 x86-64 (x64/AMD64/Intel 64) instruction set
  • IA64 IA64 CPU (in x86 mode) instruction set

followed by your code. Then invoke NASM to assemble that file, and observe the exit status and error message from NASM. There are similar directives for TASM/MASM in case you're not using NASM.


An example:

test8086.asm

[cpu 8086]
cmovne eax,ebx  ; Not a part of the 8086 instruction set


C:\nasm>nasm -f bin -o test8086.com test8086.asm
test8086.asm:2: error: no instruction for this cpu level

C:\nasm>echo %errorlevel%
1

Upvotes: 7

Related Questions