What's this assembly doing?What's 'fs:[0]' doing and how can I execute it step by step?What could this...
Not a Long-Winded Riddle
A fantasy book with seven white haired women on the cover
How do you funnel food off a cutting board?
How to write cases in LaTeX?
What is the wife of a henpecked husband called?
Can you determine if focus is sharp without diopter adjustment if your sight is imperfect?
How to politely refuse in-office gym instructor for steroids and protein
How much mayhem could I cause as a fish?
Need help with a circuit diagram where the motor does not seem to have any connection to ground. Error with diagram? Or am i missing something?
Is there a way to store 9th-level spells in a Glyph of Warding or similar method?
The No-Straight Maze
Translation needed for 130 years old church document
What's the oldest plausible frozen specimen for a Jurassic Park style story-line?
If angels and devils are the same species, why would their mortal offspring appear physically different?
How do I prevent a homebrew Grappling Hook feature from trivializing Tomb of Annihilation?
Do authors have to be politically correct in article-writing?
What species should be used for storage of human minds?
In harmony: key or the flow?
Does Skippy chunky peanut butter contain trans fat?
Coworker asking me to not bring cakes due to self control issue. What should I do?
Renting a 2CV in France
Am I correct in stating that the study of topology is purely theoretical?
Plausible reason to leave the Solar System?
Midterm in Mathematics Courses
What's this assembly doing?
What's 'fs:[0]' doing and how can I execute it step by step?What could this sequence of assembly instructions possibly mean?What is this assembly code doing with the command line argumentsWhat C construct could generate this assembly sequence?xDAx9Fb - what's that?What's the packer/encrypter used with this fileIssues rewriting portions of DOS app's assemblyWhat exactly is this piece of assembly code doing?How should i read this assembly?How did this 80286 detection code work?
I have been trying to figure out the assembly for part of a DOS game and there is an operation that keeps getting called that uses all 4 registers. I can see what each line does but I can't for the life of me figure out what all the code together is meant be doing.
Can anyone give me some idea?
The code is:
seg000:3825 some_math_op_on_regs proc far; CODE XREF: sub_72C6+19FP
seg000:3825 ; sub_72C6+1DDP ...
seg000:3825 cmp cl, 10h
seg000:3828 jnb short loc_383A ; Jump if CF=0
seg000:382A mov bx, dx ; c register is < 16; move d to b
seg000:382C shr ax, cl ; Shift a right by value in c (logical)
seg000:382E sar dx, cl ; Shift d right by value in c (arithmetic)
seg000:3830 neg cl ; Negate c (2's complement)
seg000:3832 add cl, 10h ; Add 16 to c
seg000:3835 shl bx, cl ; Shift b left by value in c (logical)
seg000:3837 or ax, bx ; OR a and b, store result in a
seg000:3839 retf
seg000:383A ; --------------------------------------------------------------------
seg000:383A
seg000:383A loc_383A: ; CODE XREF: some_math_op_on_regs+3j
seg000:383A sub cl, 10h ; c register is >= 16; subtract 16 from c
seg000:383D xchg ax, dx ; Switch values in a and d
seg000:383E cwd ; Convert word to doubleword
seg000:383F sar ax, cl ; Shift a right by value in c (arithmetic)
seg000:3841 retf
seg000:3841 some_math_op_on_regs endp
disassembly x86 dos
New contributor
add a comment |
I have been trying to figure out the assembly for part of a DOS game and there is an operation that keeps getting called that uses all 4 registers. I can see what each line does but I can't for the life of me figure out what all the code together is meant be doing.
Can anyone give me some idea?
The code is:
seg000:3825 some_math_op_on_regs proc far; CODE XREF: sub_72C6+19FP
seg000:3825 ; sub_72C6+1DDP ...
seg000:3825 cmp cl, 10h
seg000:3828 jnb short loc_383A ; Jump if CF=0
seg000:382A mov bx, dx ; c register is < 16; move d to b
seg000:382C shr ax, cl ; Shift a right by value in c (logical)
seg000:382E sar dx, cl ; Shift d right by value in c (arithmetic)
seg000:3830 neg cl ; Negate c (2's complement)
seg000:3832 add cl, 10h ; Add 16 to c
seg000:3835 shl bx, cl ; Shift b left by value in c (logical)
seg000:3837 or ax, bx ; OR a and b, store result in a
seg000:3839 retf
seg000:383A ; --------------------------------------------------------------------
seg000:383A
seg000:383A loc_383A: ; CODE XREF: some_math_op_on_regs+3j
seg000:383A sub cl, 10h ; c register is >= 16; subtract 16 from c
seg000:383D xchg ax, dx ; Switch values in a and d
seg000:383E cwd ; Convert word to doubleword
seg000:383F sar ax, cl ; Shift a right by value in c (arithmetic)
seg000:3841 retf
seg000:3841 some_math_op_on_regs endp
disassembly x86 dos
New contributor
add a comment |
I have been trying to figure out the assembly for part of a DOS game and there is an operation that keeps getting called that uses all 4 registers. I can see what each line does but I can't for the life of me figure out what all the code together is meant be doing.
Can anyone give me some idea?
The code is:
seg000:3825 some_math_op_on_regs proc far; CODE XREF: sub_72C6+19FP
seg000:3825 ; sub_72C6+1DDP ...
seg000:3825 cmp cl, 10h
seg000:3828 jnb short loc_383A ; Jump if CF=0
seg000:382A mov bx, dx ; c register is < 16; move d to b
seg000:382C shr ax, cl ; Shift a right by value in c (logical)
seg000:382E sar dx, cl ; Shift d right by value in c (arithmetic)
seg000:3830 neg cl ; Negate c (2's complement)
seg000:3832 add cl, 10h ; Add 16 to c
seg000:3835 shl bx, cl ; Shift b left by value in c (logical)
seg000:3837 or ax, bx ; OR a and b, store result in a
seg000:3839 retf
seg000:383A ; --------------------------------------------------------------------
seg000:383A
seg000:383A loc_383A: ; CODE XREF: some_math_op_on_regs+3j
seg000:383A sub cl, 10h ; c register is >= 16; subtract 16 from c
seg000:383D xchg ax, dx ; Switch values in a and d
seg000:383E cwd ; Convert word to doubleword
seg000:383F sar ax, cl ; Shift a right by value in c (arithmetic)
seg000:3841 retf
seg000:3841 some_math_op_on_regs endp
disassembly x86 dos
New contributor
I have been trying to figure out the assembly for part of a DOS game and there is an operation that keeps getting called that uses all 4 registers. I can see what each line does but I can't for the life of me figure out what all the code together is meant be doing.
Can anyone give me some idea?
The code is:
seg000:3825 some_math_op_on_regs proc far; CODE XREF: sub_72C6+19FP
seg000:3825 ; sub_72C6+1DDP ...
seg000:3825 cmp cl, 10h
seg000:3828 jnb short loc_383A ; Jump if CF=0
seg000:382A mov bx, dx ; c register is < 16; move d to b
seg000:382C shr ax, cl ; Shift a right by value in c (logical)
seg000:382E sar dx, cl ; Shift d right by value in c (arithmetic)
seg000:3830 neg cl ; Negate c (2's complement)
seg000:3832 add cl, 10h ; Add 16 to c
seg000:3835 shl bx, cl ; Shift b left by value in c (logical)
seg000:3837 or ax, bx ; OR a and b, store result in a
seg000:3839 retf
seg000:383A ; --------------------------------------------------------------------
seg000:383A
seg000:383A loc_383A: ; CODE XREF: some_math_op_on_regs+3j
seg000:383A sub cl, 10h ; c register is >= 16; subtract 16 from c
seg000:383D xchg ax, dx ; Switch values in a and d
seg000:383E cwd ; Convert word to doubleword
seg000:383F sar ax, cl ; Shift a right by value in c (arithmetic)
seg000:3841 retf
seg000:3841 some_math_op_on_regs endp
disassembly x86 dos
disassembly x86 dos
New contributor
New contributor
edited 6 hours ago
perror
11.3k1767130
11.3k1767130
New contributor
asked 9 hours ago
JezJez
1334
1334
New contributor
New contributor
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
This looks like a 32-bit shift right compiler helper. In 16-bit era, 32-bit numbers were represented by a pair of registers, in this case ax:dx
. The check for 16 is an optimization: if the shift is over 16, the low register value is lost completely, so it can be discarded and replaced by dx>>(shift-16)
, while the high register is filled with the sign bit as the result of the cwd
instruction. Here's the (lightly) commented source code from the Borland C runtime library which seems to match yours:
;[]-----------------------------------------------------------------[]
;| H_LRSH.ASM -- long shift right |
;[]-----------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 5.0
;
; Copyright (c) 1987, 1992 by Borland International
; All Rights Reserved.
;
INCLUDE RULES.ASI
_TEXT segment public byte 'CODE'
assume cs:_TEXT
public LXRSH@
public F_LXRSH@
public N_LXRSH@
N_LXRSH@:
pop bx ;fix up for far return
push cs
push bx
LXRSH@:
F_LXRSH@:
cmp cl,16
jae lsh@small
mov bx,dx ; save the high bits
shr ax,cl ; now shift each half
sar dx,cl
;
; We now have a hole in AX where the lower bits of
; DX should have been shifted. So we must take our
; copy of DX and do a reverse shift to get the proper
; bits to be or'ed into AX.
;
neg cl
add cl,16
shl bx,cl
or ax,bx
retf
lsh@small:
sub cl,16 ; for shifts more than 15, do this
; short sequence.
xchg ax,dx ;
cwd ; We have now done a shift by 16.
sar ax,cl ; Now shift the remainder.
retf
_TEXT ends
end
add a comment |
It appears to be a 32 bit right shift with the 32 bit number provided in dx:ax
, and cl
being the number of bits to shift.
If you assume cl
is over 16, a right shift by more than 16 bit only needs to care about the upper 16 bit, which are stored in dx
, because the lower 16 bit are shifted out anyway.
So that's exactly what the 2nd block does. If cl
larger than 16, move dx
(upper 16 bit) into ax
and convert it to a 32 bit number, subtract 16 from cl
because this is implicitly done by ignoring the lower 16 bit, then shift the upper part (which is now dx:ax
thanks to the cwd
) by that number.
I didn't try to understand the top part, but my assumption is it does exactly the same for shift widths below 16 bits.
Basically, it's a 32 bit right shift done in 16 bit architecture.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "489"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Jez is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2freverseengineering.stackexchange.com%2fquestions%2f20712%2fwhats-this-assembly-doing%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
This looks like a 32-bit shift right compiler helper. In 16-bit era, 32-bit numbers were represented by a pair of registers, in this case ax:dx
. The check for 16 is an optimization: if the shift is over 16, the low register value is lost completely, so it can be discarded and replaced by dx>>(shift-16)
, while the high register is filled with the sign bit as the result of the cwd
instruction. Here's the (lightly) commented source code from the Borland C runtime library which seems to match yours:
;[]-----------------------------------------------------------------[]
;| H_LRSH.ASM -- long shift right |
;[]-----------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 5.0
;
; Copyright (c) 1987, 1992 by Borland International
; All Rights Reserved.
;
INCLUDE RULES.ASI
_TEXT segment public byte 'CODE'
assume cs:_TEXT
public LXRSH@
public F_LXRSH@
public N_LXRSH@
N_LXRSH@:
pop bx ;fix up for far return
push cs
push bx
LXRSH@:
F_LXRSH@:
cmp cl,16
jae lsh@small
mov bx,dx ; save the high bits
shr ax,cl ; now shift each half
sar dx,cl
;
; We now have a hole in AX where the lower bits of
; DX should have been shifted. So we must take our
; copy of DX and do a reverse shift to get the proper
; bits to be or'ed into AX.
;
neg cl
add cl,16
shl bx,cl
or ax,bx
retf
lsh@small:
sub cl,16 ; for shifts more than 15, do this
; short sequence.
xchg ax,dx ;
cwd ; We have now done a shift by 16.
sar ax,cl ; Now shift the remainder.
retf
_TEXT ends
end
add a comment |
This looks like a 32-bit shift right compiler helper. In 16-bit era, 32-bit numbers were represented by a pair of registers, in this case ax:dx
. The check for 16 is an optimization: if the shift is over 16, the low register value is lost completely, so it can be discarded and replaced by dx>>(shift-16)
, while the high register is filled with the sign bit as the result of the cwd
instruction. Here's the (lightly) commented source code from the Borland C runtime library which seems to match yours:
;[]-----------------------------------------------------------------[]
;| H_LRSH.ASM -- long shift right |
;[]-----------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 5.0
;
; Copyright (c) 1987, 1992 by Borland International
; All Rights Reserved.
;
INCLUDE RULES.ASI
_TEXT segment public byte 'CODE'
assume cs:_TEXT
public LXRSH@
public F_LXRSH@
public N_LXRSH@
N_LXRSH@:
pop bx ;fix up for far return
push cs
push bx
LXRSH@:
F_LXRSH@:
cmp cl,16
jae lsh@small
mov bx,dx ; save the high bits
shr ax,cl ; now shift each half
sar dx,cl
;
; We now have a hole in AX where the lower bits of
; DX should have been shifted. So we must take our
; copy of DX and do a reverse shift to get the proper
; bits to be or'ed into AX.
;
neg cl
add cl,16
shl bx,cl
or ax,bx
retf
lsh@small:
sub cl,16 ; for shifts more than 15, do this
; short sequence.
xchg ax,dx ;
cwd ; We have now done a shift by 16.
sar ax,cl ; Now shift the remainder.
retf
_TEXT ends
end
add a comment |
This looks like a 32-bit shift right compiler helper. In 16-bit era, 32-bit numbers were represented by a pair of registers, in this case ax:dx
. The check for 16 is an optimization: if the shift is over 16, the low register value is lost completely, so it can be discarded and replaced by dx>>(shift-16)
, while the high register is filled with the sign bit as the result of the cwd
instruction. Here's the (lightly) commented source code from the Borland C runtime library which seems to match yours:
;[]-----------------------------------------------------------------[]
;| H_LRSH.ASM -- long shift right |
;[]-----------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 5.0
;
; Copyright (c) 1987, 1992 by Borland International
; All Rights Reserved.
;
INCLUDE RULES.ASI
_TEXT segment public byte 'CODE'
assume cs:_TEXT
public LXRSH@
public F_LXRSH@
public N_LXRSH@
N_LXRSH@:
pop bx ;fix up for far return
push cs
push bx
LXRSH@:
F_LXRSH@:
cmp cl,16
jae lsh@small
mov bx,dx ; save the high bits
shr ax,cl ; now shift each half
sar dx,cl
;
; We now have a hole in AX where the lower bits of
; DX should have been shifted. So we must take our
; copy of DX and do a reverse shift to get the proper
; bits to be or'ed into AX.
;
neg cl
add cl,16
shl bx,cl
or ax,bx
retf
lsh@small:
sub cl,16 ; for shifts more than 15, do this
; short sequence.
xchg ax,dx ;
cwd ; We have now done a shift by 16.
sar ax,cl ; Now shift the remainder.
retf
_TEXT ends
end
This looks like a 32-bit shift right compiler helper. In 16-bit era, 32-bit numbers were represented by a pair of registers, in this case ax:dx
. The check for 16 is an optimization: if the shift is over 16, the low register value is lost completely, so it can be discarded and replaced by dx>>(shift-16)
, while the high register is filled with the sign bit as the result of the cwd
instruction. Here's the (lightly) commented source code from the Borland C runtime library which seems to match yours:
;[]-----------------------------------------------------------------[]
;| H_LRSH.ASM -- long shift right |
;[]-----------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 5.0
;
; Copyright (c) 1987, 1992 by Borland International
; All Rights Reserved.
;
INCLUDE RULES.ASI
_TEXT segment public byte 'CODE'
assume cs:_TEXT
public LXRSH@
public F_LXRSH@
public N_LXRSH@
N_LXRSH@:
pop bx ;fix up for far return
push cs
push bx
LXRSH@:
F_LXRSH@:
cmp cl,16
jae lsh@small
mov bx,dx ; save the high bits
shr ax,cl ; now shift each half
sar dx,cl
;
; We now have a hole in AX where the lower bits of
; DX should have been shifted. So we must take our
; copy of DX and do a reverse shift to get the proper
; bits to be or'ed into AX.
;
neg cl
add cl,16
shl bx,cl
or ax,bx
retf
lsh@small:
sub cl,16 ; for shifts more than 15, do this
; short sequence.
xchg ax,dx ;
cwd ; We have now done a shift by 16.
sar ax,cl ; Now shift the remainder.
retf
_TEXT ends
end
answered 5 hours ago
Igor Skochinsky♦Igor Skochinsky
24.4k44587
24.4k44587
add a comment |
add a comment |
It appears to be a 32 bit right shift with the 32 bit number provided in dx:ax
, and cl
being the number of bits to shift.
If you assume cl
is over 16, a right shift by more than 16 bit only needs to care about the upper 16 bit, which are stored in dx
, because the lower 16 bit are shifted out anyway.
So that's exactly what the 2nd block does. If cl
larger than 16, move dx
(upper 16 bit) into ax
and convert it to a 32 bit number, subtract 16 from cl
because this is implicitly done by ignoring the lower 16 bit, then shift the upper part (which is now dx:ax
thanks to the cwd
) by that number.
I didn't try to understand the top part, but my assumption is it does exactly the same for shift widths below 16 bits.
Basically, it's a 32 bit right shift done in 16 bit architecture.
add a comment |
It appears to be a 32 bit right shift with the 32 bit number provided in dx:ax
, and cl
being the number of bits to shift.
If you assume cl
is over 16, a right shift by more than 16 bit only needs to care about the upper 16 bit, which are stored in dx
, because the lower 16 bit are shifted out anyway.
So that's exactly what the 2nd block does. If cl
larger than 16, move dx
(upper 16 bit) into ax
and convert it to a 32 bit number, subtract 16 from cl
because this is implicitly done by ignoring the lower 16 bit, then shift the upper part (which is now dx:ax
thanks to the cwd
) by that number.
I didn't try to understand the top part, but my assumption is it does exactly the same for shift widths below 16 bits.
Basically, it's a 32 bit right shift done in 16 bit architecture.
add a comment |
It appears to be a 32 bit right shift with the 32 bit number provided in dx:ax
, and cl
being the number of bits to shift.
If you assume cl
is over 16, a right shift by more than 16 bit only needs to care about the upper 16 bit, which are stored in dx
, because the lower 16 bit are shifted out anyway.
So that's exactly what the 2nd block does. If cl
larger than 16, move dx
(upper 16 bit) into ax
and convert it to a 32 bit number, subtract 16 from cl
because this is implicitly done by ignoring the lower 16 bit, then shift the upper part (which is now dx:ax
thanks to the cwd
) by that number.
I didn't try to understand the top part, but my assumption is it does exactly the same for shift widths below 16 bits.
Basically, it's a 32 bit right shift done in 16 bit architecture.
It appears to be a 32 bit right shift with the 32 bit number provided in dx:ax
, and cl
being the number of bits to shift.
If you assume cl
is over 16, a right shift by more than 16 bit only needs to care about the upper 16 bit, which are stored in dx
, because the lower 16 bit are shifted out anyway.
So that's exactly what the 2nd block does. If cl
larger than 16, move dx
(upper 16 bit) into ax
and convert it to a 32 bit number, subtract 16 from cl
because this is implicitly done by ignoring the lower 16 bit, then shift the upper part (which is now dx:ax
thanks to the cwd
) by that number.
I didn't try to understand the top part, but my assumption is it does exactly the same for shift widths below 16 bits.
Basically, it's a 32 bit right shift done in 16 bit architecture.
answered 5 hours ago
Johann AydinbasJohann Aydinbas
57628
57628
add a comment |
add a comment |
Jez is a new contributor. Be nice, and check out our Code of Conduct.
Jez is a new contributor. Be nice, and check out our Code of Conduct.
Jez is a new contributor. Be nice, and check out our Code of Conduct.
Jez is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Reverse Engineering Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2freverseengineering.stackexchange.com%2fquestions%2f20712%2fwhats-this-assembly-doing%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown